Compare commits
82 Commits
citadel
...
gnome-3-34
Author | SHA1 | Date | |
---|---|---|---|
|
f6ace7a325 | ||
|
c38196dd85 | ||
|
059af4c4cd | ||
|
aba60dcac8 | ||
|
3d7ee7856f | ||
|
0a50b6ea01 | ||
|
c5dd9a9341 | ||
|
2756806f84 | ||
|
bb9c286e3f | ||
|
cf2ab505a0 | ||
|
b7389b328c | ||
|
99d948559b | ||
|
f21a0ff458 | ||
|
ec852ab265 | ||
|
a8bb7c0a2a | ||
|
8a8c6e2f23 | ||
|
f7fe7bc676 | ||
|
a35f9a5226 | ||
|
fb74394d58 | ||
|
9f7b1bd677 | ||
|
afd2ce2353 | ||
|
61fccf188a | ||
|
5043e6d6bd | ||
|
7be1729cde | ||
|
f92cb46b02 | ||
|
56902542c7 | ||
|
523eea4527 | ||
|
a7b0e96304 | ||
|
bb24df2f9d | ||
|
9150cbca3e | ||
|
35bb67bb2f | ||
|
d4c2f9d0ef | ||
|
e211c68a5c | ||
|
af95883807 | ||
|
91f41105d5 | ||
|
45fa520cca | ||
|
334762ee9e | ||
|
88e3dfa104 | ||
|
4b89314813 | ||
|
a9fa4cc49e | ||
|
9476c9c4ca | ||
|
24df43d579 | ||
|
363336e4a1 | ||
|
070c784412 | ||
|
455eb67a49 | ||
|
23cc59f52a | ||
|
19bb459a57 | ||
|
48477443fa | ||
|
40b2fbf465 | ||
|
7800bd2158 | ||
|
d4f07410a1 | ||
|
64b62de5df | ||
|
9b0d42309b | ||
|
cf249ab870 | ||
|
c752682ab9 | ||
|
a6e4ef862c | ||
|
8d2365b7b9 | ||
|
03219f745d | ||
|
7d34dee77f | ||
|
f0e59ea088 | ||
|
f8a90f6583 | ||
|
aa1d297bdf | ||
|
b88f7d0655 | ||
|
59daa4192c | ||
|
d08cd1f523 | ||
|
a85cddada0 | ||
|
ae8568a2e0 | ||
|
4a3ca40c48 | ||
|
e257be64d0 | ||
|
96ac00b53c | ||
|
7e8884a601 | ||
|
ef726bf313 | ||
|
a43c22e3af | ||
|
22b6a09cd7 | ||
|
65110968c5 | ||
|
d142f59478 | ||
|
c1ecd304e7 | ||
|
750c5acd30 | ||
|
246150d8b6 | ||
|
072a9a4842 | ||
|
7149da3f4f | ||
|
6c2a82258e |
@ -1,6 +1,5 @@
|
||||
#!/usr/bin/bash
|
||||
|
||||
shell_branch=$(git describe --contains --all HEAD)
|
||||
mutter_target=
|
||||
|
||||
git clone https://gitlab.gnome.org/GNOME/mutter.git
|
||||
@ -26,8 +25,7 @@ if [ "$CI_MERGE_REQUEST_TARGET_BRANCH_NAME" ]; then
|
||||
fi
|
||||
|
||||
if [ -z "$mutter_target" ]; then
|
||||
mutter_target=$(git branch -r -l origin/$shell_branch)
|
||||
mutter_target=${mutter_target:-$(git branch -r -l ${shell_branch#remotes/})}
|
||||
mutter_target=$(git branch -r -l origin/$CI_COMMIT_REF_NAME)
|
||||
mutter_target=${mutter_target:-origin/master}
|
||||
echo Using $mutter_target instead
|
||||
fi
|
||||
|
75
NEWS
75
NEWS
@ -1,3 +1,78 @@
|
||||
3.34.5
|
||||
======
|
||||
* Leave overview when locking the screen [Jonas D.; !1043]
|
||||
* Avoid IO on the main thread [Christian; !1050]
|
||||
* Fix OSK layout fallback for unsupported variants [Florian; #2471]
|
||||
* Fix high-contrast/symbolic icon mix-up [Florian; #2414]
|
||||
* Misc. bug fixes and cleanups [Jonas Å., Florian; !1032, #2386]
|
||||
|
||||
Contributors:
|
||||
Jonas Dreßler, Christian Hergert, Florian Müllner, Jwtiyar Nariman,
|
||||
Jonas Ådahl
|
||||
|
||||
Translators:
|
||||
Jwtiyar Nariman [ckb]
|
||||
|
||||
3.34.4
|
||||
======
|
||||
* Switch screen-recorder back to VP8 [Björn; #256]
|
||||
|
||||
Contributors:
|
||||
Björn Daase
|
||||
|
||||
Translators:
|
||||
Jor Teron [mjw], Dušan Kazik [sk]
|
||||
|
||||
3.34.3
|
||||
======
|
||||
* polkitAgent: Fix confirming via keyboard when password-less [Jonas; #2066]
|
||||
* Misc. bug fixes and cleanups [Florian; !906]
|
||||
|
||||
Contributors:
|
||||
Jonas Dreßler, Florian Müllner
|
||||
|
||||
3.34.2
|
||||
======
|
||||
* Fix unredirection after cancelled animations [Florian; #1788]
|
||||
* Use cached coordinates for window sorting in overview [Andrew; !763]
|
||||
* Include shadow in window screenshots [Robert; !762]
|
||||
* Use correct timezones for events [Milan, Florian; !806, #1895]
|
||||
* Adjust style of system menu action buttons [monday; !802]
|
||||
* Fix windows getting stuck on screen if closed while animating [Florian; !815]
|
||||
* Hide stopped spinner in top bar [Joonas; !834]
|
||||
* Reuse existing icons when updating the app picker grid [Georges; !841]
|
||||
* Fix not-responding dialog size when using geometry scaling [Jonas; !783]
|
||||
* Fix battery icon glitch in "100% but charging" case [Philip; !814]
|
||||
* Update window titles in app menu [Florian; #1830]
|
||||
* Improve modifier-less keyboard navigation of switcher popups [Florian; #1883]
|
||||
* Use better OSK layout fallback for unsupported variants [Florian; #1907]
|
||||
* Fix creating app folders with no pre-existing folders [Jonas; #1652]
|
||||
* Improve DND page switching in app picker [Florian, Jonas; #1693]
|
||||
* Show polkit confirmation dialog for users with no password [Joaquim; !829]
|
||||
* Fix interacting with applications when magnifier is enabled [Jonas; !754]
|
||||
* Tweak styling of notifications/media constrols [Joonas; !855, !865]
|
||||
* Fix disable command of gnome-extensions tool [Florian; #1946]
|
||||
* Enable clean session shutdown after gnome-shell failure [Benjamin; !858]
|
||||
* Also remove scaled keys when texture cache is cleared [Daniel; !567]
|
||||
* Don't show overflow indicator in switchers that fit screen [Florian; #1834]
|
||||
* Place launched applications into a systemd scope [Benjamin; !863]
|
||||
* Fix weather forecasts for automatic location when Weather is not sandboxed
|
||||
[Florian; #1823]
|
||||
* Dismiss switcher popups when a system modal dialogs opens [Florian; #1536]
|
||||
* Misc. bug fixes and cleanups [Marco, Philip, Florian, cunidev, Jonas, Joonas;
|
||||
!758, !749, !777, !811, #1884, !823, !840, !782, !847, #1836, !852, !851,
|
||||
!788, #1916, !866, !884]
|
||||
|
||||
Contributors:
|
||||
Marco Trevisan (Treviño), Benjamin Berg, Philip Chimento, Milan Crha,
|
||||
Jonas Dreßler, Joonas Henriksson, Robert Mader, Daniel García Moreno,
|
||||
Florian Müllner, Georges Basile Stavracas Neto, Joaquim Rocha, Andrew Watson,
|
||||
cunidev, monday
|
||||
|
||||
Translators:
|
||||
Stas Solovey [ru], Ricardo Silva Veloso [pt_BR], Yi-Jyun Pan [zh_TW],
|
||||
Umarzuki Bin Mochlis Moktar [ms]
|
||||
|
||||
3.34.1
|
||||
======
|
||||
* Fix "Frequent" view icons disappearing on hover [Jonas D.; #1502]
|
||||
|
@ -30,3 +30,6 @@
|
||||
|
||||
/* Define if fdwalk is available in libc */
|
||||
#mesondefine HAVE_FDWALK
|
||||
|
||||
/* Define if we have gnome-desktop systemd utils */
|
||||
#mesondefine HAVE_GNOME_SYSTEMD
|
||||
|
@ -1,11 +1,12 @@
|
||||
[Unit]
|
||||
Description=Disable GNOME Shell extensions after failure
|
||||
# Note that this unit must not conflict with anything, and must
|
||||
# be able to run in parallel with the gnome-session-shutdown.target.
|
||||
DefaultDependencies=no
|
||||
|
||||
# Only disable extensions for a short period of time after login.
|
||||
# This means we err on the side of failing the first login after a broken
|
||||
# extension was installed.
|
||||
Requisite=gnome-session-stable.timer
|
||||
# We want to disable extensions only if gnome-shell has flagged the extensions
|
||||
# to be a likely cause of trouble.
|
||||
ConditionPathExists=%t/gnome-shell-disable-extensions
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
|
@ -1061,9 +1061,9 @@ StScrollBar {
|
||||
}
|
||||
.calendar-today {
|
||||
font-weight: bold;
|
||||
//color: lighten($fg_color,10%);
|
||||
//background-color: darken($bg_color,5%);
|
||||
border: 1px solid $_bubble_borders_color;
|
||||
color: lighten($fg_color,5%);
|
||||
background-color: darken($bg_color,5%);
|
||||
// border: 1px solid lighten($_bubble_borders_color,20%);
|
||||
}
|
||||
.calendar-day-with-events {
|
||||
color: lighten($fg_color,10%);
|
||||
@ -1153,14 +1153,21 @@ StScrollBar {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.message-close-button {
|
||||
color: lighten($fg_color, 15%);
|
||||
&:hover { color: if($variant=='light', lighten($fg_color, 30%), darken($fg_color, 10%)); }
|
||||
&:active { color: if($variant=='light', lighten($fg_color, 40%), darken($fg_color, 20%)); }
|
||||
}
|
||||
|
||||
.message-media-control {
|
||||
padding: 12px;
|
||||
color: lighten($fg_color, 15%);
|
||||
|
||||
&:last-child:ltr { padding-right: 18px; }
|
||||
&:last-child:rtl { padding-left: 18px; }
|
||||
&:hover { color: $fg_color; }
|
||||
&:insensitive { color: darken($fg_color,40%); }
|
||||
&:hover { color: if($variant=='light', lighten($fg_color, 30%), darken($fg_color, 10%)); }
|
||||
&:active { color: if($variant=='light', lighten($fg_color, 40%), darken($fg_color, 20%)); }
|
||||
&:insensitive { color: if($variant=='light', lighten($fg_color, 50%), darken($fg_color, 40%)); }
|
||||
}
|
||||
|
||||
.media-message-cover-icon {
|
||||
@ -1209,12 +1216,11 @@ StScrollBar {
|
||||
&:hover, &:focus {
|
||||
background-color: $_hover_bg_color;
|
||||
color: $fg_color;
|
||||
border: none;
|
||||
padding: 14px;
|
||||
}
|
||||
&:active {
|
||||
background-color: $selected_bg_color;
|
||||
color: $selected_fg_color;
|
||||
border-color: $selected_borders_color;
|
||||
}
|
||||
|
||||
& > StIcon { icon-size: 16px; }
|
||||
|
@ -15,6 +15,5 @@ var LOCALEDIR = '@datadir@/locale';
|
||||
/* other standard directories */
|
||||
var LIBEXECDIR = '@libexecdir@';
|
||||
var PKGDATADIR = '@datadir@/@PACKAGE_NAME@';
|
||||
var VPNDIR = '@vpndir@';
|
||||
/* g-i package versions */
|
||||
var LIBMUTTER_API_VERSION = '@LIBMUTTER_API_VERSION@'
|
||||
|
@ -40,6 +40,15 @@ var IntrospectService = class {
|
||||
});
|
||||
|
||||
this._syncRunningApplications();
|
||||
|
||||
this._whitelistMap = new Map();
|
||||
APP_WHITELIST.forEach(appName => {
|
||||
Gio.DBus.watch_name(Gio.BusType.SESSION,
|
||||
appName,
|
||||
Gio.BusNameWatcherFlags.NONE,
|
||||
(conn, name, owner) => this._whitelistMap.set(name, owner),
|
||||
(conn, name) => this._whitelistMap.delete(name));
|
||||
});
|
||||
}
|
||||
|
||||
_isStandaloneApp(app) {
|
||||
@ -51,7 +60,7 @@ var IntrospectService = class {
|
||||
}
|
||||
|
||||
_isSenderWhitelisted(sender) {
|
||||
return APP_WHITELIST.includes(sender);
|
||||
return [...this._whitelistMap.values()].includes(sender);
|
||||
}
|
||||
|
||||
_getSandboxedAppId(app) {
|
||||
|
@ -7,7 +7,6 @@ jsconf.set10('HAVE_BLUETOOTH', bt_dep.found())
|
||||
jsconf.set10('HAVE_NETWORKMANAGER', have_networkmanager)
|
||||
jsconf.set('datadir', datadir)
|
||||
jsconf.set('libexecdir', libexecdir)
|
||||
jsconf.set('vpndir', vpndir)
|
||||
|
||||
config_js = configure_file(
|
||||
input: 'config.js.in',
|
||||
|
@ -3,7 +3,7 @@
|
||||
formatTime, formatTimeSpan, createTimeLabel, insertSorted,
|
||||
makeCloseButton, ensureActorVisibleInScrollView */
|
||||
|
||||
const { Clutter, Gio, GLib, GObject, Shell, St } = imports.gi;
|
||||
const { Clutter, Gio, GLib, GObject, Shell, St, GnomeDesktop } = imports.gi;
|
||||
const Gettext = imports.gettext;
|
||||
|
||||
const Main = imports.ui.main;
|
||||
@ -127,6 +127,14 @@ function trySpawn(argv) {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
// Async call, we don't need the reply though
|
||||
try {
|
||||
GnomeDesktop.start_systemd_scope(argv[0], pid, null, null, null, () => {});
|
||||
} catch (err) {
|
||||
// Ignore error; it likely means GnomeDesktop is too old
|
||||
}
|
||||
|
||||
// Dummy child watch; we don't want to double-fork internally
|
||||
// because then we lose the parent-child relationship, which
|
||||
// can break polkit. See https://bugzilla.redhat.com//show_bug.cgi?id=819275
|
||||
|
@ -32,6 +32,7 @@ var WeatherClient = class {
|
||||
this._gclueStarting = false;
|
||||
this._gclueLocationChangedId = 0;
|
||||
|
||||
this._needsAuth = true;
|
||||
this._weatherAuthorized = false;
|
||||
this._permStore = new PermissionStore.PermissionStore((proxy, error) => {
|
||||
if (error) {
|
||||
@ -142,7 +143,7 @@ var WeatherClient = class {
|
||||
get _useAutoLocation() {
|
||||
return this._autoLocationRequested &&
|
||||
this._locationSettings.get_boolean('enabled') &&
|
||||
this._weatherAuthorized;
|
||||
(!this._needsAuth || this._weatherAuthorized);
|
||||
}
|
||||
|
||||
_onWeatherProxyReady(o, res) {
|
||||
@ -175,6 +176,13 @@ var WeatherClient = class {
|
||||
|
||||
if (hadApp !== haveApp)
|
||||
this.emit('changed');
|
||||
|
||||
let neededAuth = this._needsAuth;
|
||||
this._needsAuth = this._weatherApp === null ||
|
||||
this._weatherApp.app_info.has_key('X-Flatpak');
|
||||
|
||||
if (neededAuth !== this._needsAuth)
|
||||
this._updateAutoLocation();
|
||||
}
|
||||
|
||||
_loadInfo() {
|
||||
|
@ -3,6 +3,8 @@
|
||||
|
||||
const { Clutter, GLib, Gio, St } = imports.gi;
|
||||
|
||||
const Params = imports.misc.params;
|
||||
|
||||
var ANIMATED_ICON_UPDATE_TIMEOUT = 16;
|
||||
var SPINNER_ANIMATION_TIME = 300;
|
||||
var SPINNER_ANIMATION_DELAY = 1000;
|
||||
@ -131,12 +133,22 @@ var AnimatedIcon = class extends Animation {
|
||||
};
|
||||
|
||||
var Spinner = class extends AnimatedIcon {
|
||||
constructor(size, animate = false) {
|
||||
constructor(size, params) {
|
||||
// Compatibility with older callers
|
||||
if (params === true || params === false)
|
||||
params = { animate: params };
|
||||
|
||||
params = Params.parse(params, {
|
||||
animate: false,
|
||||
hideOnStop: false,
|
||||
});
|
||||
let file = Gio.File.new_for_uri('resource:///org/gnome/shell/theme/process-working.svg');
|
||||
super(file, size);
|
||||
|
||||
this.actor.opacity = 0;
|
||||
this._animate = animate;
|
||||
this._animate = params.animate;
|
||||
this._hideOnStop = params.hideOnStop;
|
||||
this.actor.visible = !this._hideOnStop;
|
||||
}
|
||||
|
||||
_onDestroy() {
|
||||
@ -146,6 +158,7 @@ var Spinner = class extends AnimatedIcon {
|
||||
|
||||
play() {
|
||||
this.actor.remove_all_transitions();
|
||||
this.actor.show();
|
||||
|
||||
if (this._animate) {
|
||||
super.play();
|
||||
@ -169,11 +182,18 @@ var Spinner = class extends AnimatedIcon {
|
||||
opacity: 0,
|
||||
duration: SPINNER_ANIMATION_TIME,
|
||||
mode: Clutter.AnimationMode.LINEAR,
|
||||
onComplete: () => super.stop()
|
||||
onComplete: () => {
|
||||
super.stop();
|
||||
if (this._hideOnStop)
|
||||
this.actor.hide();
|
||||
},
|
||||
});
|
||||
} else {
|
||||
this.actor.opacity = 0;
|
||||
super.stop();
|
||||
|
||||
if (this._hideOnStop)
|
||||
this.actor.hide();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -40,6 +40,9 @@ var PAGE_SWITCH_TIME = 300;
|
||||
var APP_ICON_SCALE_IN_TIME = 500;
|
||||
var APP_ICON_SCALE_IN_DELAY = 700;
|
||||
|
||||
const OVERSHOOT_THRESHOLD = 20;
|
||||
const OVERSHOOT_TIMEOUT = 1000;
|
||||
|
||||
const SWITCHEROO_BUS_NAME = 'net.hadess.SwitcherooControl';
|
||||
const SWITCHEROO_OBJECT_PATH = '/net/hadess/SwitcherooControl';
|
||||
|
||||
@ -97,7 +100,10 @@ function _findBestFolderName(apps) {
|
||||
let commonCategories = [];
|
||||
|
||||
appInfos.reduce((categories, appInfo) => {
|
||||
for (let category of appInfo.get_categories().split(';')) {
|
||||
const appCategories = appInfo.get_categories();
|
||||
if (!appCategories)
|
||||
return categories;
|
||||
for (let category of appCategories.split(';')) {
|
||||
if (!(category in categoryCounter))
|
||||
categoryCounter[category] = 0;
|
||||
|
||||
@ -173,10 +179,11 @@ class BaseAppView {
|
||||
// Remove old app icons
|
||||
removedApps.forEach(icon => {
|
||||
let iconIndex = this._allItems.indexOf(icon);
|
||||
let id = icon.id;
|
||||
|
||||
this._allItems.splice(iconIndex, 1);
|
||||
this._grid.removeItem(icon);
|
||||
delete this._items[icon.id];
|
||||
icon.actor.destroy();
|
||||
delete this._items[id];
|
||||
});
|
||||
|
||||
// Add new app icons
|
||||
@ -308,7 +315,12 @@ var AllView = class AllView extends BaseAppView {
|
||||
|
||||
this._grid.currentPage = 0;
|
||||
this._stack.add_actor(this._grid);
|
||||
this._eventBlocker = new St.Widget({ x_expand: true, y_expand: true });
|
||||
this._eventBlocker = new St.Widget({
|
||||
x_expand: true,
|
||||
y_expand: true,
|
||||
reactive: true,
|
||||
visible: false,
|
||||
});
|
||||
this._stack.add_actor(this._eventBlocker);
|
||||
|
||||
box.add_actor(this._stack);
|
||||
@ -335,12 +347,16 @@ var AllView = class AllView extends BaseAppView {
|
||||
});
|
||||
this._eventBlocker.add_action(this._clickAction);
|
||||
|
||||
this._currentPopup = null;
|
||||
this._displayingPopup = false;
|
||||
this._currentPopupDestroyId = 0;
|
||||
|
||||
this._availWidth = 0;
|
||||
this._availHeight = 0;
|
||||
|
||||
this._lastOvershootY = -1;
|
||||
this._lastOvershootTimeoutId = 0;
|
||||
|
||||
Main.overview.connect('hidden', () => this.goToPage(0));
|
||||
this._grid.connect('space-opened', () => {
|
||||
let fadeEffect = this._scrollView.get_effect('fade');
|
||||
@ -377,8 +393,6 @@ var AllView = class AllView extends BaseAppView {
|
||||
|
||||
Main.overview.connect('item-drag-begin', this._onDragBegin.bind(this));
|
||||
Main.overview.connect('item-drag-end', this._onDragEnd.bind(this));
|
||||
|
||||
this._nEventBlockerInhibits = 0;
|
||||
}
|
||||
|
||||
_redisplay() {
|
||||
@ -425,7 +439,7 @@ var AllView = class AllView extends BaseAppView {
|
||||
}
|
||||
|
||||
_loadApps() {
|
||||
let newApps = [];
|
||||
let appIcons = [];
|
||||
this._appInfoList = Shell.AppSystem.get_default().get_installed().filter(appInfo => {
|
||||
try {
|
||||
(appInfo.get_id()); // catch invalid file encodings
|
||||
@ -450,7 +464,7 @@ var AllView = class AllView extends BaseAppView {
|
||||
icon.connect('name-changed', this._itemNameChanged.bind(this));
|
||||
icon.connect('apps-changed', this._redisplay.bind(this));
|
||||
}
|
||||
newApps.push(icon);
|
||||
appIcons.push(icon);
|
||||
this.folderIcons.push(icon);
|
||||
});
|
||||
|
||||
@ -463,14 +477,19 @@ var AllView = class AllView extends BaseAppView {
|
||||
let favoritesWritable = global.settings.is_writable('favorite-apps');
|
||||
|
||||
apps.forEach(appId => {
|
||||
let app = appSys.lookup_app(appId);
|
||||
let icon = this._items[appId];
|
||||
if (!icon) {
|
||||
let app = appSys.lookup_app(appId);
|
||||
|
||||
let icon = new AppIcon(app,
|
||||
{ isDraggable: favoritesWritable });
|
||||
newApps.push(icon);
|
||||
icon = new AppIcon(app, {
|
||||
isDraggable: favoritesWritable,
|
||||
});
|
||||
}
|
||||
|
||||
appIcons.push(icon);
|
||||
});
|
||||
|
||||
return newApps;
|
||||
return appIcons;
|
||||
}
|
||||
|
||||
// Overridden from BaseAppView
|
||||
@ -648,7 +667,7 @@ var AllView = class AllView extends BaseAppView {
|
||||
addFolderPopup(popup) {
|
||||
this._stack.add_actor(popup.actor);
|
||||
popup.connect('open-state-changed', (popup, isOpen) => {
|
||||
this._eventBlocker.reactive = isOpen;
|
||||
this._eventBlocker.visible = isOpen;
|
||||
|
||||
if (this._currentPopup) {
|
||||
this._currentPopup.actor.disconnect(this._currentPopupDestroyId);
|
||||
@ -662,7 +681,7 @@ var AllView = class AllView extends BaseAppView {
|
||||
this._currentPopupDestroyId = popup.actor.connect('destroy', () => {
|
||||
this._currentPopup = null;
|
||||
this._currentPopupDestroyId = 0;
|
||||
this._eventBlocker.reactive = false;
|
||||
this._eventBlocker.visible = false;
|
||||
});
|
||||
}
|
||||
this._updateIconOpacities(isOpen);
|
||||
@ -730,29 +749,58 @@ var AllView = class AllView extends BaseAppView {
|
||||
this.folderIcons[i].adaptToSize(availWidth, availHeight);
|
||||
}
|
||||
|
||||
_resetOvershoot() {
|
||||
if (this._lastOvershootTimeoutId)
|
||||
GLib.source_remove(this._lastOvershootTimeoutId);
|
||||
this._lastOvershootTimeoutId = 0;
|
||||
this._lastOvershootY = -1;
|
||||
}
|
||||
|
||||
_handleDragOvershoot(dragEvent) {
|
||||
let [, gridY] = this.actor.get_transformed_position();
|
||||
let [, gridHeight] = this.actor.get_transformed_size();
|
||||
let gridBottom = gridY + gridHeight;
|
||||
|
||||
// Within the grid boundaries, or already animating
|
||||
if (dragEvent.y > gridY && dragEvent.y < gridBottom ||
|
||||
this._adjustment.get_transition('value') != null) {
|
||||
// Already animating
|
||||
if (this._adjustment.get_transition('value') !== null)
|
||||
return;
|
||||
|
||||
// Within the grid boundaries
|
||||
if (dragEvent.y > gridY && dragEvent.y < gridBottom) {
|
||||
// Check whether we moved out the area of the last switch
|
||||
if (Math.abs(this._lastOvershootY - dragEvent.y) > OVERSHOOT_THRESHOLD)
|
||||
this._resetOvershoot();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Moving above the grid
|
||||
// Still in the area of the previous page switch
|
||||
if (this._lastOvershootY >= 0)
|
||||
return;
|
||||
|
||||
let currentY = this._adjustment.value;
|
||||
if (dragEvent.y <= gridY && currentY > 0) {
|
||||
this.goToPage(this._grid.currentPage - 1);
|
||||
return;
|
||||
}
|
||||
|
||||
// Moving below the grid
|
||||
let maxY = this._adjustment.upper - this._adjustment.page_size;
|
||||
if (dragEvent.y >= gridBottom && currentY < maxY) {
|
||||
|
||||
if (dragEvent.y <= gridY && currentY > 0)
|
||||
this.goToPage(this._grid.currentPage - 1);
|
||||
else if (dragEvent.y >= gridBottom && currentY < maxY)
|
||||
this.goToPage(this._grid.currentPage + 1);
|
||||
}
|
||||
else
|
||||
return; // don't go beyond first/last page
|
||||
|
||||
this._lastOvershootY = dragEvent.y;
|
||||
|
||||
if (this._lastOvershootTimeoutId > 0)
|
||||
GLib.source_remove(this._lastOvershootTimeoutId);
|
||||
|
||||
this._lastOvershootTimeoutId =
|
||||
GLib.timeout_add(GLib.PRIORITY_DEFAULT, OVERSHOOT_TIMEOUT, () => {
|
||||
this._resetOvershoot();
|
||||
this._handleDragOvershoot(dragEvent);
|
||||
return GLib.SOURCE_REMOVE;
|
||||
});
|
||||
GLib.Source.set_name_by_id(this._lastOvershootTimeoutId,
|
||||
'[gnome-shell] this._lastOvershootTimeoutId');
|
||||
}
|
||||
|
||||
_onDragBegin() {
|
||||
@ -760,6 +808,8 @@ var AllView = class AllView extends BaseAppView {
|
||||
dragMotion: this._onDragMotion.bind(this)
|
||||
};
|
||||
DND.addDragMonitor(this._dragMonitor);
|
||||
|
||||
this._eventBlocker.visible = false;
|
||||
}
|
||||
|
||||
_onDragMotion(dragEvent) {
|
||||
@ -782,6 +832,9 @@ var AllView = class AllView extends BaseAppView {
|
||||
DND.removeDragMonitor(this._dragMonitor);
|
||||
this._dragMonitor = null;
|
||||
}
|
||||
|
||||
this._eventBlocker.visible = this._currentPopup !== null;
|
||||
this._resetOvershoot();
|
||||
}
|
||||
|
||||
_canAccept(source) {
|
||||
@ -815,19 +868,6 @@ var AllView = class AllView extends BaseAppView {
|
||||
return true;
|
||||
}
|
||||
|
||||
inhibitEventBlocker() {
|
||||
this._nEventBlockerInhibits++;
|
||||
this._eventBlocker.visible = this._nEventBlockerInhibits == 0;
|
||||
}
|
||||
|
||||
uninhibitEventBlocker() {
|
||||
if (this._nEventBlockerInhibits === 0)
|
||||
throw new Error('Not inhibited');
|
||||
|
||||
this._nEventBlockerInhibits--;
|
||||
this._eventBlocker.visible = this._nEventBlockerInhibits == 0;
|
||||
}
|
||||
|
||||
createFolder(apps) {
|
||||
let newFolderId = GLib.uuid_string_random();
|
||||
|
||||
@ -918,8 +958,12 @@ var FrequentView = class FrequentView extends BaseAppView {
|
||||
for (let i = 0; i < mostUsed.length; i++) {
|
||||
if (!mostUsed[i].get_app_info().should_show())
|
||||
continue;
|
||||
let appIcon = new AppIcon(mostUsed[i],
|
||||
{ isDraggable: favoritesWritable });
|
||||
let appIcon = this._items[mostUsed[i].get_id()];
|
||||
if (!appIcon) {
|
||||
appIcon = new AppIcon(mostUsed[i], {
|
||||
isDraggable: favoritesWritable,
|
||||
});
|
||||
}
|
||||
apps.push(appIcon);
|
||||
}
|
||||
|
||||
@ -1349,7 +1393,10 @@ var FolderView = class FolderView extends BaseAppView {
|
||||
if (apps.some(appIcon => appIcon.id == appId))
|
||||
return;
|
||||
|
||||
let icon = new AppIcon(app);
|
||||
let icon = this._items[appId];
|
||||
if (!icon)
|
||||
icon = new AppIcon(app);
|
||||
|
||||
apps.push(icon);
|
||||
};
|
||||
|
||||
@ -1387,15 +1434,15 @@ var FolderView = class FolderView extends BaseAppView {
|
||||
// Remove the folder if this is the last app icon; otherwise,
|
||||
// just remove the icon
|
||||
if (folderApps.length == 0) {
|
||||
let settings = new Gio.Settings({ schema_id: 'org.gnome.desktop.app-folders' });
|
||||
let folders = settings.get_strv('folder-children');
|
||||
folders.splice(folders.indexOf(this._id), 1);
|
||||
settings.set_strv('folder-children', folders);
|
||||
|
||||
// Resetting all keys deletes the relocatable schema
|
||||
let keys = this._folder.settings_schema.list_keys();
|
||||
for (let key of keys)
|
||||
this._folder.reset(key);
|
||||
|
||||
let settings = new Gio.Settings({ schema_id: 'org.gnome.desktop.app-folders' });
|
||||
let folders = settings.get_strv('folder-children');
|
||||
folders.splice(folders.indexOf(this._id), 1);
|
||||
settings.set_strv('folder-children', folders);
|
||||
} else {
|
||||
this._folder.set_strv('apps', folderApps);
|
||||
}
|
||||
@ -1487,8 +1534,6 @@ var FolderIcon = class FolderIcon {
|
||||
dragMotion: this._onDragMotion.bind(this),
|
||||
};
|
||||
DND.addDragMonitor(this._dragMonitor);
|
||||
|
||||
this._parentView.inhibitEventBlocker();
|
||||
}
|
||||
|
||||
_onDragMotion(dragEvent) {
|
||||
@ -1504,7 +1549,6 @@ var FolderIcon = class FolderIcon {
|
||||
|
||||
_onDragEnd() {
|
||||
this.actor.remove_style_pseudo_class('drop');
|
||||
this._parentView.uninhibitEventBlocker();
|
||||
DND.removeDragMonitor(this._dragMonitor);
|
||||
}
|
||||
|
||||
@ -1994,17 +2038,10 @@ var AppIcon = class AppIcon {
|
||||
x_fill: true,
|
||||
y_fill: true });
|
||||
|
||||
this._dot = new St.Widget({ style_class: 'app-well-app-running-dot',
|
||||
layout_manager: new Clutter.BinLayout(),
|
||||
x_expand: true, y_expand: true,
|
||||
x_align: Clutter.ActorAlign.CENTER,
|
||||
y_align: Clutter.ActorAlign.END });
|
||||
|
||||
this._iconContainer = new St.Widget({ layout_manager: new Clutter.BinLayout(),
|
||||
x_expand: true, y_expand: true });
|
||||
|
||||
this.actor.set_child(this._iconContainer);
|
||||
this._iconContainer.add_child(this._dot);
|
||||
|
||||
this.actor._delegate = this;
|
||||
|
||||
@ -2021,6 +2058,16 @@ var AppIcon = class AppIcon {
|
||||
this.icon = new IconGrid.BaseIcon(app.get_name(), iconParams);
|
||||
this._iconContainer.add_child(this.icon);
|
||||
|
||||
this._dot = new St.Widget({
|
||||
style_class: 'app-well-app-running-dot',
|
||||
layout_manager: new Clutter.BinLayout(),
|
||||
x_expand: true,
|
||||
y_expand: true,
|
||||
x_align: Clutter.ActorAlign.CENTER,
|
||||
y_align: Clutter.ActorAlign.END,
|
||||
});
|
||||
this._iconContainer.add_child(this._dot);
|
||||
|
||||
this.actor.label_actor = this.icon.label;
|
||||
|
||||
this.actor.connect('leave-event', this._onLeaveEvent.bind(this));
|
||||
@ -2051,6 +2098,7 @@ var AppIcon = class AppIcon {
|
||||
});
|
||||
}
|
||||
|
||||
this._dragMonitor = null;
|
||||
this._itemDragBeginId = Main.overview.connect(
|
||||
'item-drag-begin', this._onDragBegin.bind(this));
|
||||
this._itemDragEndId = Main.overview.connect(
|
||||
@ -2075,6 +2123,12 @@ var AppIcon = class AppIcon {
|
||||
}
|
||||
if (this._stateChangedId > 0)
|
||||
this.app.disconnect(this._stateChangedId);
|
||||
|
||||
if (this._dragMonitor) {
|
||||
DND.removeDragMonitor(this._dragMonitor);
|
||||
this._dragMonitor = null;
|
||||
}
|
||||
|
||||
if (this._draggable) {
|
||||
if (this._dragging)
|
||||
Main.overview.endItemDrag(this);
|
||||
|
@ -1,7 +1,7 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
/* exported CloseDialog */
|
||||
|
||||
const { Clutter, Gio, GLib, GObject, Meta, Shell } = imports.gi;
|
||||
const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
|
||||
|
||||
const Dialog = imports.ui.dialog;
|
||||
const Main = imports.ui.main;
|
||||
@ -46,6 +46,18 @@ var CloseDialog = GObject.registerClass({
|
||||
return new Dialog.MessageDialogContent({ icon, title, subtitle });
|
||||
}
|
||||
|
||||
_updateScale() {
|
||||
// Since this is a child of MetaWindowActor (which, for Wayland clients,
|
||||
// applies the geometry scale factor to its children itself, see
|
||||
// meta_window_actor_set_geometry_scale()), make sure we don't apply
|
||||
// the factor twice in the end.
|
||||
if (this._window.get_client_type() !== Meta.WindowClientType.WAYLAND)
|
||||
return;
|
||||
|
||||
let { scaleFactor } = St.ThemeContext.get_for_stage(global.stage);
|
||||
this._dialog.set_scale(1 / scaleFactor, 1 / scaleFactor);
|
||||
}
|
||||
|
||||
_initDialog() {
|
||||
if (this._dialog)
|
||||
return;
|
||||
@ -64,6 +76,11 @@ var CloseDialog = GObject.registerClass({
|
||||
key: Clutter.Escape });
|
||||
|
||||
global.focus_manager.add_group(this._dialog);
|
||||
|
||||
let themeContext = St.ThemeContext.get_for_stage(global.stage);
|
||||
themeContext.connect('notify::scale-factor', this._updateScale.bind(this));
|
||||
|
||||
this._updateScale();
|
||||
}
|
||||
|
||||
_addWindowEffect() {
|
||||
@ -145,10 +162,10 @@ var CloseDialog = GObject.registerClass({
|
||||
this._addWindowEffect();
|
||||
this._initDialog();
|
||||
|
||||
this._dialog.scale_y = 0;
|
||||
this._dialog.set_pivot_point(0.5, 0.5);
|
||||
this._dialog._dialog.scale_y = 0;
|
||||
this._dialog._dialog.set_pivot_point(0.5, 0.5);
|
||||
|
||||
this._dialog.ease({
|
||||
this._dialog._dialog.ease({
|
||||
scale_y: 1,
|
||||
mode: Clutter.AnimationMode.LINEAR,
|
||||
duration: DIALOG_TRANSITION_TIME,
|
||||
@ -175,7 +192,8 @@ var CloseDialog = GObject.registerClass({
|
||||
this._dialog = null;
|
||||
this._removeWindowEffect();
|
||||
|
||||
dialog.ease({
|
||||
dialog.makeInactive();
|
||||
dialog._dialog.ease({
|
||||
scale_y: 0,
|
||||
mode: Clutter.AnimationMode.LINEAR,
|
||||
duration: DIALOG_TRANSITION_TIME,
|
||||
|
@ -74,7 +74,9 @@ class KeyringDialog extends ModalDialog.ModalDialog {
|
||||
ShellEntry.addContextMenu(this._passwordEntry, { isPassword: true });
|
||||
this._passwordEntry.clutter_text.connect('activate', this._onPasswordActivate.bind(this));
|
||||
|
||||
this._workSpinner = new Animation.Spinner(WORK_SPINNER_ICON_SIZE, true);
|
||||
this._workSpinner = new Animation.Spinner(WORK_SPINNER_ICON_SIZE, {
|
||||
animate: true,
|
||||
});
|
||||
|
||||
if (rtl) {
|
||||
layout.attach(this._workSpinner.actor, 0, row, 1, 1);
|
||||
|
@ -4,13 +4,15 @@
|
||||
const { Clutter, Gio, GLib, GObject, NM, Pango, Shell, St } = imports.gi;
|
||||
const Signals = imports.signals;
|
||||
|
||||
const Config = imports.misc.config;
|
||||
const Dialog = imports.ui.dialog;
|
||||
const Main = imports.ui.main;
|
||||
const MessageTray = imports.ui.messageTray;
|
||||
const ModalDialog = imports.ui.modalDialog;
|
||||
const ShellEntry = imports.ui.shellEntry;
|
||||
|
||||
Gio._promisify(Shell.NetworkAgent.prototype,
|
||||
'search_vpn_plugin', 'search_vpn_plugin_finish');
|
||||
|
||||
const VPN_UI_GROUP = 'VPN Plugin UI';
|
||||
|
||||
var NetworkSecretDialog = GObject.registerClass(
|
||||
@ -622,14 +624,6 @@ var NetworkAgent = class {
|
||||
this._vpnRequests = { };
|
||||
this._notifications = { };
|
||||
|
||||
this._pluginDir = Gio.file_new_for_path(Config.VPNDIR);
|
||||
try {
|
||||
let monitor = this._pluginDir.monitor(Gio.FileMonitorFlags.NONE, null);
|
||||
monitor.connect('changed', () => (this._vpnCacheBuilt = false));
|
||||
} catch (e) {
|
||||
log(`Failed to create monitor for VPN plugin dir: ${e.message}`);
|
||||
}
|
||||
|
||||
this._native.connect('new-request', this._newRequest.bind(this));
|
||||
this._native.connect('cancel-request', this._cancelRequest.bind(this));
|
||||
|
||||
@ -769,13 +763,11 @@ var NetworkAgent = class {
|
||||
}
|
||||
}
|
||||
|
||||
_vpnRequest(requestId, connection, hints, flags) {
|
||||
async _vpnRequest(requestId, connection, hints, flags) {
|
||||
let vpnSetting = connection.get_setting_vpn();
|
||||
let serviceType = vpnSetting.service_type;
|
||||
|
||||
this._buildVPNServiceCache();
|
||||
|
||||
let binary = this._vpnBinaries[serviceType];
|
||||
let binary = await this._findAuthBinary(serviceType);
|
||||
if (!binary) {
|
||||
log('Invalid VPN service type (cannot find authentication binary)');
|
||||
|
||||
@ -791,36 +783,30 @@ var NetworkAgent = class {
|
||||
this._vpnRequests[requestId] = vpnRequest;
|
||||
}
|
||||
|
||||
_buildVPNServiceCache() {
|
||||
if (this._vpnCacheBuilt)
|
||||
return;
|
||||
async _findAuthBinary(serviceType) {
|
||||
let plugin;
|
||||
|
||||
this._vpnCacheBuilt = true;
|
||||
this._vpnBinaries = { };
|
||||
try {
|
||||
plugin = await this._native.search_vpn_plugin(serviceType);
|
||||
} catch (e) {
|
||||
logError(e);
|
||||
return null;
|
||||
}
|
||||
|
||||
NM.VpnPluginInfo.list_load().forEach(plugin => {
|
||||
let service = plugin.get_service();
|
||||
let fileName = plugin.get_auth_dialog();
|
||||
let supportsHints = plugin.supports_hints();
|
||||
let externalUIMode = false;
|
||||
const fileName = plugin.get_auth_dialog();
|
||||
if (!GLib.file_test(fileName, GLib.FileTest.IS_EXECUTABLE)) {
|
||||
log('VPN plugin at %s is not executable'.format(fileName));
|
||||
return null;
|
||||
}
|
||||
|
||||
let prop = plugin.lookup_property('GNOME', 'supports-external-ui-mode');
|
||||
if (prop) {
|
||||
prop = prop.trim().toLowerCase();
|
||||
externalUIMode = ['true', 'yes', 'on', '1'].includes(prop);
|
||||
}
|
||||
const prop = plugin.lookup_property('GNOME', 'supports-external-ui-mode');
|
||||
const trimmedProp = prop ? prop.trim().toLowerCase() : '';
|
||||
|
||||
if (GLib.file_test(fileName, GLib.FileTest.IS_EXECUTABLE)) {
|
||||
let binary = { fileName, externalUIMode, supportsHints };
|
||||
this._vpnBinaries[service] = binary;
|
||||
|
||||
plugin.get_aliases().forEach(alias => {
|
||||
this._vpnBinaries[alias] = binary;
|
||||
});
|
||||
} else {
|
||||
log('VPN plugin at %s is not executable'.format(fileName));
|
||||
}
|
||||
});
|
||||
return {
|
||||
fileName,
|
||||
supportsHints: plugin.supports_hints(),
|
||||
externalUIMode: ['true', 'yes', 'on', '1'].includes(trimmedProp),
|
||||
};
|
||||
}
|
||||
};
|
||||
var Component = NetworkAgent;
|
||||
|
@ -11,6 +11,11 @@ const ModalDialog = imports.ui.modalDialog;
|
||||
const ShellEntry = imports.ui.shellEntry;
|
||||
const UserWidget = imports.ui.userWidget;
|
||||
|
||||
const DialogMode = {
|
||||
AUTH: 0,
|
||||
CONFIRM: 1,
|
||||
};
|
||||
|
||||
var DIALOG_ICON_SIZE = 48;
|
||||
|
||||
var WORK_SPINNER_ICON_SIZE = 16;
|
||||
@ -51,47 +56,32 @@ var AuthenticationDialog = GObject.registerClass({
|
||||
userName = userNames[0];
|
||||
|
||||
this._user = AccountsService.UserManager.get_default().get_user(userName);
|
||||
let userRealName = this._user.get_real_name();
|
||||
this._userLoadedId = this._user.connect('notify::is_loaded',
|
||||
this._onUserChanged.bind(this));
|
||||
this._userChangedId = this._user.connect('changed',
|
||||
this._onUserChanged.bind(this));
|
||||
|
||||
// Special case 'root'
|
||||
let userIsRoot = false;
|
||||
if (userName == 'root') {
|
||||
userIsRoot = true;
|
||||
userRealName = _("Administrator");
|
||||
}
|
||||
let userBox = new St.BoxLayout({
|
||||
style_class: 'polkit-dialog-user-layout',
|
||||
vertical: false,
|
||||
});
|
||||
content.messageBox.add(userBox);
|
||||
|
||||
if (userIsRoot) {
|
||||
let userLabel = new St.Label(({ style_class: 'polkit-dialog-user-root-label',
|
||||
text: userRealName }));
|
||||
content.messageBox.add(userLabel, { x_fill: false,
|
||||
x_align: St.Align.START });
|
||||
} else {
|
||||
let userBox = new St.BoxLayout({ style_class: 'polkit-dialog-user-layout',
|
||||
vertical: false });
|
||||
content.messageBox.add(userBox);
|
||||
this._userAvatar = new UserWidget.Avatar(this._user,
|
||||
{ iconSize: DIALOG_ICON_SIZE,
|
||||
styleClass: 'polkit-dialog-user-icon' });
|
||||
this._userAvatar.actor.hide();
|
||||
userBox.add(this._userAvatar.actor,
|
||||
{ x_fill: true,
|
||||
y_fill: false,
|
||||
x_align: St.Align.END,
|
||||
y_align: St.Align.START });
|
||||
let userLabel = new St.Label(({ style_class: 'polkit-dialog-user-label',
|
||||
text: userRealName }));
|
||||
userBox.add(userLabel,
|
||||
{ x_fill: true,
|
||||
y_fill: false,
|
||||
x_align: St.Align.END,
|
||||
y_align: St.Align.MIDDLE });
|
||||
}
|
||||
this._userAvatar = new UserWidget.Avatar(this._user, {
|
||||
iconSize: DIALOG_ICON_SIZE,
|
||||
styleClass: 'polkit-dialog-user-icon',
|
||||
});
|
||||
this._userAvatar.actor.hide();
|
||||
userBox.add_child(this._userAvatar.actor);
|
||||
|
||||
this._onUserChanged();
|
||||
this._userLabel = new St.Label({
|
||||
style_class: userName === 'root'
|
||||
? 'polkit-dialog-user-root-label'
|
||||
: 'polkit-dialog-user-label',
|
||||
x_expand: true,
|
||||
y_align: Clutter.ActorAlign.CENTER,
|
||||
});
|
||||
|
||||
if (userName === 'root')
|
||||
this._userLabel.text = _('Administrator');
|
||||
|
||||
userBox.add_child(this._userLabel);
|
||||
|
||||
this._passwordBox = new St.BoxLayout({ vertical: false, style_class: 'prompt-dialog-password-box' });
|
||||
content.messageBox.add(this._passwordBox);
|
||||
@ -105,10 +95,11 @@ var AuthenticationDialog = GObject.registerClass({
|
||||
this._passwordBox.add(this._passwordEntry,
|
||||
{ expand: true });
|
||||
|
||||
this._workSpinner = new Animation.Spinner(WORK_SPINNER_ICON_SIZE, true);
|
||||
this._workSpinner = new Animation.Spinner(WORK_SPINNER_ICON_SIZE, {
|
||||
animate: true,
|
||||
});
|
||||
this._passwordBox.add(this._workSpinner.actor);
|
||||
|
||||
this.setInitialKeyFocus(this._passwordEntry);
|
||||
this._passwordBox.hide();
|
||||
|
||||
this._errorMessageLabel = new St.Label({ style_class: 'prompt-dialog-error-label' });
|
||||
@ -144,8 +135,16 @@ var AuthenticationDialog = GObject.registerClass({
|
||||
|
||||
this._doneEmitted = false;
|
||||
|
||||
this._mode = -1;
|
||||
|
||||
this._identityToAuth = Polkit.UnixUser.new_for_name(userName);
|
||||
this._cookie = cookie;
|
||||
|
||||
this._userLoadedId = this._user.connect('notify::is-loaded',
|
||||
this._onUserChanged.bind(this));
|
||||
this._userChangedId = this._user.connect('changed',
|
||||
this._onUserChanged.bind(this));
|
||||
this._onUserChanged();
|
||||
}
|
||||
|
||||
_setWorking(working) {
|
||||
@ -155,8 +154,9 @@ var AuthenticationDialog = GObject.registerClass({
|
||||
this._workSpinner.stop();
|
||||
}
|
||||
|
||||
performAuthentication() {
|
||||
_initiateSession() {
|
||||
this._destroySession();
|
||||
|
||||
this._session = new PolkitAgent.Session({ identity: this._identityToAuth,
|
||||
cookie: this._cookie });
|
||||
this._sessionCompletedId = this._session.connect('completed', this._onSessionCompleted.bind(this));
|
||||
@ -216,7 +216,10 @@ var AuthenticationDialog = GObject.registerClass({
|
||||
}
|
||||
|
||||
_onAuthenticateButtonPressed() {
|
||||
this._onEntryActivate();
|
||||
if (this._mode === DialogMode.CONFIRM)
|
||||
this._initiateSession();
|
||||
else
|
||||
this._onEntryActivate();
|
||||
}
|
||||
|
||||
_onSessionCompleted(session, gainedAuthorization) {
|
||||
@ -247,7 +250,7 @@ var AuthenticationDialog = GObject.registerClass({
|
||||
}
|
||||
|
||||
/* Try and authenticate again */
|
||||
this.performAuthentication();
|
||||
this._initiateSession();
|
||||
}
|
||||
}
|
||||
|
||||
@ -265,9 +268,10 @@ var AuthenticationDialog = GObject.registerClass({
|
||||
|
||||
this._passwordBox.show();
|
||||
this._passwordEntry.set_text('');
|
||||
this._passwordEntry.grab_key_focus();
|
||||
this._updateSensitivity(true);
|
||||
|
||||
this._ensureOpen();
|
||||
this._passwordEntry.grab_key_focus();
|
||||
}
|
||||
|
||||
_onSessionShowError(session, text) {
|
||||
@ -303,10 +307,40 @@ var AuthenticationDialog = GObject.registerClass({
|
||||
}
|
||||
|
||||
_onUserChanged() {
|
||||
if (this._user.is_loaded && this._userAvatar) {
|
||||
if (!this._user.is_loaded)
|
||||
return;
|
||||
|
||||
let userName = this._user.get_user_name();
|
||||
let realName = this._user.get_real_name();
|
||||
|
||||
if (userName !== 'root') {
|
||||
this._userLabel.set_text(realName);
|
||||
|
||||
this._userAvatar.update();
|
||||
this._userAvatar.actor.show();
|
||||
}
|
||||
|
||||
if (this._user.get_password_mode() === AccountsService.UserPasswordMode.NONE) {
|
||||
if (this._mode === DialogMode.CONFIRM)
|
||||
return;
|
||||
|
||||
this._mode = DialogMode.CONFIRM;
|
||||
this._destroySession();
|
||||
|
||||
this._okButton.reactive = true;
|
||||
|
||||
/* We normally open the dialog when we get a "request" signal, but
|
||||
* since in this case initiating a session would perform the
|
||||
* authentication, only open the dialog and initiate the session
|
||||
* when the user confirmed. */
|
||||
this._ensureOpen();
|
||||
} else {
|
||||
if (this._mode === DialogMode.AUTH)
|
||||
return;
|
||||
|
||||
this._mode = DialogMode.AUTH;
|
||||
this._initiateSession();
|
||||
}
|
||||
}
|
||||
|
||||
cancel() {
|
||||
@ -369,19 +403,7 @@ var AuthenticationAgent = class {
|
||||
}
|
||||
|
||||
this._currentDialog = new AuthenticationDialog(actionId, message, cookie, userNames);
|
||||
|
||||
// We actually don't want to open the dialog until we know for
|
||||
// sure that we're going to interact with the user. For
|
||||
// example, if the password for the identity to auth is blank
|
||||
// (which it will be on a live CD) then there will be no
|
||||
// conversation at all... of course, we don't *know* that
|
||||
// until we actually try it.
|
||||
//
|
||||
// See https://bugzilla.gnome.org/show_bug.cgi?id=643062 for more
|
||||
// discussion.
|
||||
|
||||
this._currentDialog.connect('done', this._onDialogDone.bind(this));
|
||||
this._currentDialog.performAuthentication();
|
||||
}
|
||||
|
||||
_onCancel(_nativeAgent) {
|
||||
|
@ -51,10 +51,16 @@ class Dialog extends St.Widget {
|
||||
y_align: St.Align.START });
|
||||
}
|
||||
|
||||
_onDestroy() {
|
||||
makeInactive() {
|
||||
if (this._eventId != 0)
|
||||
this._parentActor.disconnect(this._eventId);
|
||||
this._eventId = 0;
|
||||
|
||||
this.buttonLayout.get_children().forEach(c => c.set_reactive(false));
|
||||
}
|
||||
|
||||
_onDestroy() {
|
||||
this.makeInactive();
|
||||
}
|
||||
|
||||
_modalEventHandler(actor, event) {
|
||||
|
14
js/ui/dnd.js
14
js/ui/dnd.js
@ -573,11 +573,15 @@ var _Draggable = class _Draggable {
|
||||
while (target) {
|
||||
if (target._delegate && target._delegate.acceptDrop) {
|
||||
let [r_, targX, targY] = target.transform_stage_point(dropX, dropY);
|
||||
if (target._delegate.acceptDrop(this.actor._delegate,
|
||||
this._dragActor,
|
||||
targX,
|
||||
targY,
|
||||
event.get_time())) {
|
||||
let accepted = false;
|
||||
try {
|
||||
accepted = target._delegate.acceptDrop(this.actor._delegate,
|
||||
this._dragActor, targX, targY, event.get_time());
|
||||
} catch (e) {
|
||||
// On error, skip this target
|
||||
logError(e, "Skipping drag target");
|
||||
}
|
||||
if (accepted) {
|
||||
// If it accepted the drop without taking the actor,
|
||||
// handle it ourselves.
|
||||
if (this._dragActor && this._dragActor.get_parent() == Main.uiGroup) {
|
||||
|
@ -109,8 +109,6 @@ function _easeActor(actor, params) {
|
||||
actor.set_easing_mode(params.mode);
|
||||
delete params.mode;
|
||||
|
||||
Meta.disable_unredirect_for_display(global.display);
|
||||
|
||||
let cleanup = () => Meta.enable_unredirect_for_display(global.display);
|
||||
let callback = _makeEaseCallback(params, cleanup);
|
||||
|
||||
@ -124,6 +122,11 @@ function _easeActor(actor, params) {
|
||||
let transition = animatedProps.map(p => actor.get_transition(p))
|
||||
.find(t => t !== null);
|
||||
|
||||
if (transition && transition.delay)
|
||||
transition.connect('started', () => Meta.disable_unredirect_for_display(global.display));
|
||||
else
|
||||
Meta.disable_unredirect_for_display(global.display);
|
||||
|
||||
if (transition)
|
||||
transition.connect('stopped', (t, finished) => callback(finished));
|
||||
else
|
||||
@ -145,8 +148,6 @@ function _easeActorProperty(actor, propName, target, params) {
|
||||
if (actor instanceof Clutter.Actor && !actor.mapped)
|
||||
duration = 0;
|
||||
|
||||
Meta.disable_unredirect_for_display(global.display);
|
||||
|
||||
let cleanup = () => Meta.enable_unredirect_for_display(global.display);
|
||||
let callback = _makeEaseCallback(params, cleanup);
|
||||
|
||||
@ -157,6 +158,7 @@ function _easeActorProperty(actor, propName, target, params) {
|
||||
let [obj, prop] = _getPropertyTarget(actor, propName);
|
||||
obj[prop] = target;
|
||||
|
||||
Meta.disable_unredirect_for_display(global.display);
|
||||
callback(true);
|
||||
|
||||
return;
|
||||
@ -172,6 +174,11 @@ function _easeActorProperty(actor, propName, target, params) {
|
||||
|
||||
transition.set_to(target);
|
||||
|
||||
if (transition.delay)
|
||||
transition.connect('started', () => Meta.disable_unredirect_for_display(global.display));
|
||||
else
|
||||
Meta.disable_unredirect_for_display(global.display);
|
||||
|
||||
transition.connect('stopped', (t, finished) => callback(finished));
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
/* exported init connect disconnect */
|
||||
|
||||
const { Gio, St } = imports.gi;
|
||||
const { GLib, Gio, St } = imports.gi;
|
||||
const Signals = imports.signals;
|
||||
|
||||
const ExtensionUtils = imports.misc.extensionUtils;
|
||||
@ -28,6 +28,23 @@ var ExtensionManager = class {
|
||||
}
|
||||
|
||||
init() {
|
||||
// The following file should exist for a period of time when extensions
|
||||
// are enabled after start. If it exists, then the systemd unit will
|
||||
// disable extensions should gnome-shell crash.
|
||||
// Should the file already exist from a previous login, then this is OK.
|
||||
let disableFilename = GLib.build_filenamev([GLib.get_user_runtime_dir(), 'gnome-shell-disable-extensions']);
|
||||
let disableFile = Gio.File.new_for_path(disableFilename);
|
||||
try {
|
||||
disableFile.create(Gio.FileCreateFlags.REPLACE_DESTINATION, null);
|
||||
} catch (e) {
|
||||
log(`Failed to create file ${disableFilename}: ${e.message}`);
|
||||
}
|
||||
|
||||
GLib.timeout_add_seconds(GLib.PRIORITY_DEFAULT, 60, () => {
|
||||
FileUtils.deleteGFile(disableFile);
|
||||
return GLib.SOURCE_REMOVE;
|
||||
});
|
||||
|
||||
this._sessionUpdated();
|
||||
}
|
||||
|
||||
|
@ -466,10 +466,17 @@ Signals.addSignalMethods(Key.prototype);
|
||||
|
||||
var KeyboardModel = class {
|
||||
constructor(groupName) {
|
||||
try {
|
||||
this._model = this._loadModel(groupName);
|
||||
} catch (e) {
|
||||
this._model = this._loadModel('us');
|
||||
let names = [groupName];
|
||||
if (groupName.includes('+'))
|
||||
names.push(groupName.replace(/\+.*/, ''));
|
||||
names.push('us');
|
||||
|
||||
for (let i = 0; i < names.length; i++) {
|
||||
try {
|
||||
this._model = this._loadModel(names[i]);
|
||||
break;
|
||||
} catch (e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -887,7 +894,7 @@ var EmojiSelection = class EmojiSelection {
|
||||
this._emojiPager.connect('emoji', (pager, str) => {
|
||||
this.emit('emoji-selected', str);
|
||||
});
|
||||
this.actor.add(this._emojiPager.actor, { expand: true });
|
||||
this.actor.add(this._emojiPager, { expand: true });
|
||||
|
||||
this._pageIndicator = new PageIndicators.PageIndicators(false);
|
||||
this.actor.add(this._pageIndicator, { expand: true, x_fill: false, y_fill: false });
|
||||
|
@ -189,6 +189,7 @@ var LayoutManager = GObject.registerClass({
|
||||
'startup-complete': {},
|
||||
'startup-prepared': {},
|
||||
'monitors-changed': {},
|
||||
'system-modal-opened': {},
|
||||
'keyboard-visible-changed': { param_types: [GObject.TYPE_BOOLEAN] } },
|
||||
}, class LayoutManager extends GObject.Object {
|
||||
_init() {
|
||||
|
@ -127,6 +127,8 @@ var Magnifier = class Magnifier {
|
||||
* Show the system mouse pointer.
|
||||
*/
|
||||
showSystemCursor() {
|
||||
if (this._cursorTracker.set_keep_focus_while_hidden)
|
||||
this._cursorTracker.set_keep_focus_while_hidden(false);
|
||||
this._cursorTracker.set_pointer_visible(true);
|
||||
}
|
||||
|
||||
@ -135,6 +137,8 @@ var Magnifier = class Magnifier {
|
||||
* Hide the system mouse pointer.
|
||||
*/
|
||||
hideSystemCursor() {
|
||||
if (this._cursorTracker.set_keep_focus_while_hidden)
|
||||
this._cursorTracker.set_keep_focus_while_hidden(true);
|
||||
this._cursorTracker.set_pointer_visible(false);
|
||||
}
|
||||
|
||||
@ -169,7 +173,7 @@ var Magnifier = class Magnifier {
|
||||
// Make sure system mouse pointer is shown when all zoom regions are
|
||||
// invisible.
|
||||
if (!activate)
|
||||
this._cursorTracker.set_pointer_visible(true);
|
||||
this.showSystemCursor();
|
||||
|
||||
// Notify interested parties of this change
|
||||
this.emit('active-changed', activate);
|
||||
|
@ -333,7 +333,10 @@ var Message = class Message {
|
||||
|
||||
let closeIcon = new St.Icon({ icon_name: 'window-close-symbolic',
|
||||
icon_size: 16 });
|
||||
this._closeButton = new St.Button({ child: closeIcon, opacity: 0 });
|
||||
this._closeButton = new St.Button({
|
||||
style_class: 'message-close-button',
|
||||
child: closeIcon, opacity: 0,
|
||||
});
|
||||
titleBox.add_actor(this._closeButton);
|
||||
|
||||
this._bodyStack = new St.Widget({ x_expand: true });
|
||||
|
@ -216,6 +216,8 @@ var ModalDialog = GObject.registerClass({
|
||||
if (!Main.pushModal(this, params))
|
||||
return false;
|
||||
|
||||
Main.layoutManager.emit('system-modal-opened');
|
||||
|
||||
this._hasModal = true;
|
||||
if (this._savedKeyFocus) {
|
||||
this._savedKeyFocus.grab_key_focus();
|
||||
|
@ -199,7 +199,11 @@ var Overview = class {
|
||||
}
|
||||
|
||||
_sessionUpdated() {
|
||||
this.isDummy = !Main.sessionMode.hasOverview;
|
||||
const { hasOverview } = Main.sessionMode;
|
||||
if (!hasOverview)
|
||||
this.hide();
|
||||
|
||||
this.isDummy = !hasOverview;
|
||||
this._createOverview();
|
||||
}
|
||||
|
||||
|
@ -170,9 +170,13 @@ class AppMenu extends PopupMenu.PopupMenu {
|
||||
let windows = this._app.get_windows();
|
||||
windows.forEach(window => {
|
||||
let title = window.title || this._app.get_name();
|
||||
this._windowSection.addAction(title, event => {
|
||||
let item = this._windowSection.addAction(title, event => {
|
||||
Main.activateWindow(window, event.get_time());
|
||||
});
|
||||
let id = window.connect('notify::title', () => {
|
||||
item.label.text = window.title || this._app.get_name();
|
||||
});
|
||||
item.connect('destroy', () => window.disconnect(id));
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -234,7 +238,10 @@ var AppMenuButton = GObject.registerClass({
|
||||
this._overviewHidingId = Main.overview.connect('hiding', this._sync.bind(this));
|
||||
this._overviewShowingId = Main.overview.connect('showing', this._sync.bind(this));
|
||||
|
||||
this._spinner = new Animation.Spinner(PANEL_ICON_SIZE, true);
|
||||
this._spinner = new Animation.Spinner(PANEL_ICON_SIZE, {
|
||||
animate: true,
|
||||
hideOnStop: true,
|
||||
});
|
||||
this._container.add_actor(this._spinner.actor);
|
||||
|
||||
let menu = new AppMenu(this);
|
||||
|
@ -804,6 +804,7 @@ var PopupMenu = class extends PopupMenuBase {
|
||||
this._keyPressId = this.sourceActor.connect('key-press-event',
|
||||
this._onKeyPress.bind(this));
|
||||
|
||||
this._systemModalOpenedId = 0;
|
||||
this._openedSubMenu = null;
|
||||
}
|
||||
|
||||
@ -878,6 +879,11 @@ var PopupMenu = class extends PopupMenuBase {
|
||||
if (this.isEmpty())
|
||||
return;
|
||||
|
||||
if (!this._systemModalOpenedId) {
|
||||
this._systemModalOpenedId =
|
||||
Main.layoutManager.connect('system-modal-opened', () => this.close());
|
||||
}
|
||||
|
||||
this.isOpen = true;
|
||||
|
||||
this._boxPointer.setPosition(this.sourceActor, this._arrowAlignment);
|
||||
@ -908,6 +914,11 @@ var PopupMenu = class extends PopupMenuBase {
|
||||
destroy() {
|
||||
if (this._keyPressId)
|
||||
this.sourceActor.disconnect(this._keyPressId);
|
||||
|
||||
if (this._systemModalOpenedId)
|
||||
Main.layoutManager.disconnect(this._systemModalOpenedId);
|
||||
this._systemModalOpenedId = 0;
|
||||
|
||||
super.destroy();
|
||||
}
|
||||
};
|
||||
|
@ -17,6 +17,8 @@ const MessageTray = imports.ui.messageTray;
|
||||
const ShellDBus = imports.ui.shellDBus;
|
||||
const SmartcardManager = imports.misc.smartcardManager;
|
||||
|
||||
const { adjustAnimationTime } = imports.ui.environment;
|
||||
|
||||
const SCREENSAVER_SCHEMA = 'org.gnome.desktop.screensaver';
|
||||
const LOCK_ENABLED_KEY = 'lock-enabled';
|
||||
const LOCK_DELAY_KEY = 'lock-delay';
|
||||
@ -51,11 +53,17 @@ var Clock = class {
|
||||
this.actor = new St.BoxLayout({ style_class: 'screen-shield-clock',
|
||||
vertical: true });
|
||||
|
||||
this._time = new St.Label({ style_class: 'screen-shield-clock-time' });
|
||||
this._date = new St.Label({ style_class: 'screen-shield-clock-date' });
|
||||
this._time = new St.Label({
|
||||
style_class: 'screen-shield-clock-time',
|
||||
x_align: Clutter.ActorAlign.CENTER,
|
||||
});
|
||||
this._date = new St.Label({
|
||||
style_class: 'screen-shield-clock-date',
|
||||
x_align: Clutter.ActorAlign.CENTER,
|
||||
});
|
||||
|
||||
this.actor.add(this._time, { x_align: St.Align.MIDDLE });
|
||||
this.actor.add(this._date, { x_align: St.Align.MIDDLE });
|
||||
this.actor.add_child(this._time);
|
||||
this.actor.add_child(this._date);
|
||||
|
||||
this._wallClock = new GnomeDesktop.WallClock({ time_only: true });
|
||||
this._wallClock.connect('notify::clock', this._updateClock.bind(this));
|
||||
@ -91,7 +99,7 @@ var NotificationsBox = class {
|
||||
style_class: 'screen-shield-notifications-container' });
|
||||
this._scrollView.add_actor(this._notificationBox);
|
||||
|
||||
this.actor.add(this._scrollView, { x_fill: true, x_align: St.Align.START });
|
||||
this.actor.add_child(this._scrollView);
|
||||
|
||||
this._sources = new Map();
|
||||
Main.messageTray.getSources().forEach(source => {
|
||||
@ -132,10 +140,10 @@ var NotificationsBox = class {
|
||||
|
||||
_makeNotificationSource(source, box) {
|
||||
let sourceActor = new MessageTray.SourceActor(source, SUMMARY_ICON_SIZE);
|
||||
box.add(sourceActor, { y_fill: true });
|
||||
box.add_child(sourceActor);
|
||||
|
||||
let textBox = new St.BoxLayout({ vertical: true });
|
||||
box.add(textBox, { y_fill: false, y_align: St.Align.START });
|
||||
box.add_child(textBox);
|
||||
|
||||
let title = new St.Label({ text: source.title,
|
||||
style_class: 'screen-shield-notification-label' });
|
||||
@ -158,7 +166,7 @@ var NotificationsBox = class {
|
||||
box.add(sourceBin);
|
||||
|
||||
let textBox = new St.BoxLayout({ vertical: true });
|
||||
box.add(textBox, { y_fill: false, y_align: St.Align.START });
|
||||
box.add_child(textBox);
|
||||
|
||||
let title = new St.Label({ text: source.title,
|
||||
style_class: 'screen-shield-notification-label' });
|
||||
@ -220,7 +228,7 @@ var NotificationsBox = class {
|
||||
obj.sourceBox = new St.BoxLayout({ style_class: 'screen-shield-notification-source',
|
||||
x_expand: true });
|
||||
this._showSource(source, obj, obj.sourceBox);
|
||||
this._notificationBox.add(obj.sourceBox, { x_fill: false, x_align: St.Align.START });
|
||||
this._notificationBox.add_child(obj.sourceBox);
|
||||
|
||||
obj.sourceCountChangedId = source.connect('count-updated', source => {
|
||||
this._countChanged(source, obj);
|
||||
@ -832,7 +840,7 @@ var ScreenShield = class {
|
||||
|
||||
if (shouldLock) {
|
||||
let lockTimeout = Math.max(
|
||||
STANDARD_FADE_TIME,
|
||||
adjustAnimationTime(STANDARD_FADE_TIME),
|
||||
this._settings.get_uint(LOCK_DELAY_KEY) * 1000);
|
||||
this._lockTimeoutId = GLib.timeout_add(
|
||||
GLib.PRIORITY_DEFAULT,
|
||||
@ -1131,16 +1139,13 @@ var ScreenShield = class {
|
||||
vertical: true,
|
||||
style_class: 'screen-shield-contents-box' });
|
||||
this._clock = new Clock();
|
||||
this._lockScreenContentsBox.add(this._clock.actor, { x_fill: true,
|
||||
y_fill: true });
|
||||
this._lockScreenContentsBox.add_child(this._clock.actor);
|
||||
|
||||
this._lockScreenContents.add_actor(this._lockScreenContentsBox);
|
||||
|
||||
this._notificationsBox = new NotificationsBox();
|
||||
this._wakeUpScreenId = this._notificationsBox.connect('wake-up-screen', this._wakeUpScreen.bind(this));
|
||||
this._lockScreenContentsBox.add(this._notificationsBox.actor, { x_fill: true,
|
||||
y_fill: true,
|
||||
expand: true });
|
||||
this._lockScreenContentsBox.add_child(this._notificationsBox.actor);
|
||||
|
||||
this._hasLockScreen = true;
|
||||
}
|
||||
|
@ -359,7 +359,9 @@ var ShellMountPasswordDialog = GObject.registerClass({
|
||||
this._passwordEntry.clutter_text.set_password_char('\u25cf'); // ● U+25CF BLACK CIRCLE
|
||||
ShellEntry.addContextMenu(this._passwordEntry, { isPassword: true });
|
||||
this.setInitialKeyFocus(this._passwordEntry);
|
||||
this._workSpinner = new Animation.Spinner(WORK_SPINNER_ICON_SIZE, true);
|
||||
this._workSpinner = new Animation.Spinner(WORK_SPINNER_ICON_SIZE, {
|
||||
animate: true,
|
||||
});
|
||||
this._passwordEntry.secondary_icon = this._workSpinner.actor;
|
||||
|
||||
if (rtl) {
|
||||
|
@ -138,14 +138,14 @@ class ATIndicator extends PanelMenu.Button {
|
||||
interfaceSettings.is_writable(KEY_ICON_THEME),
|
||||
enabled => {
|
||||
if (enabled) {
|
||||
interfaceSettings.set_string(KEY_GTK_THEME, HIGH_CONTRAST_THEME);
|
||||
interfaceSettings.set_string(KEY_ICON_THEME, HIGH_CONTRAST_THEME);
|
||||
interfaceSettings.set_string(KEY_GTK_THEME, HIGH_CONTRAST_THEME);
|
||||
} else if (!hasHC) {
|
||||
interfaceSettings.set_string(KEY_GTK_THEME, gtkTheme);
|
||||
interfaceSettings.set_string(KEY_ICON_THEME, iconTheme);
|
||||
interfaceSettings.set_string(KEY_GTK_THEME, gtkTheme);
|
||||
} else {
|
||||
interfaceSettings.reset(KEY_GTK_THEME);
|
||||
interfaceSettings.reset(KEY_ICON_THEME);
|
||||
interfaceSettings.reset(KEY_GTK_THEME);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -111,9 +111,12 @@ var Indicator = class extends PanelMenu.SystemIndicator {
|
||||
let chargingState = this._proxy.State == UPower.DeviceState.CHARGING
|
||||
? '-charging' : '';
|
||||
let fillLevel = 10 * Math.floor(this._proxy.Percentage / 10);
|
||||
let icon = this._proxy.State == UPower.DeviceState.FULLY_CHARGED
|
||||
? 'battery-level-100-charged-symbolic'
|
||||
: `battery-level-${fillLevel}${chargingState}-symbolic`;
|
||||
let icon;
|
||||
if (this._proxy.State == UPower.DeviceState.FULLY_CHARGED ||
|
||||
fillLevel === 100)
|
||||
icon = 'battery-level-100-charged-symbolic';
|
||||
else
|
||||
icon = `battery-level-${fillLevel}${chargingState}-symbolic`;
|
||||
|
||||
// Make sure we fall back to fallback-icon-name and not GThemedIcon's
|
||||
// default fallbacks
|
||||
|
@ -46,6 +46,9 @@ var SwitcherPopup = GObject.registerClass({
|
||||
|
||||
Main.uiGroup.add_actor(this);
|
||||
|
||||
this._systemModalOpenedId =
|
||||
Main.layoutManager.connect('system-modal-opened', () => this.destroy());
|
||||
|
||||
this._haveModal = false;
|
||||
this._modifierMask = 0;
|
||||
|
||||
@ -180,6 +183,14 @@ var SwitcherPopup = GObject.registerClass({
|
||||
if (keysym == Clutter.Escape || keysym == Clutter.Tab)
|
||||
this.fadeAndDestroy();
|
||||
|
||||
// Allow to explicitly select the current item; this is particularly
|
||||
// useful for no-modifier popups
|
||||
if (keysym === Clutter.KEY_space ||
|
||||
keysym === Clutter.KEY_Return ||
|
||||
keysym === Clutter.KEY_KP_Enter ||
|
||||
keysym === Clutter.KEY_ISO_Enter)
|
||||
this._finish(event.get_time());
|
||||
|
||||
return Clutter.EVENT_STOP;
|
||||
}
|
||||
|
||||
@ -270,7 +281,7 @@ var SwitcherPopup = GObject.registerClass({
|
||||
GLib.PRIORITY_DEFAULT,
|
||||
NO_MODS_TIMEOUT,
|
||||
() => {
|
||||
this._finish(global.get_current_time());
|
||||
this._finish(global.display.get_current_time_roundtrip());
|
||||
this._noModsTimeoutId = 0;
|
||||
return GLib.SOURCE_REMOVE;
|
||||
});
|
||||
@ -304,6 +315,8 @@ var SwitcherPopup = GObject.registerClass({
|
||||
_onDestroy() {
|
||||
this._popModal();
|
||||
|
||||
Main.layoutManager.disconnect(this._systemModalOpenedId);
|
||||
|
||||
if (this._motionTimeoutId != 0)
|
||||
GLib.source_remove(this._motionTimeoutId);
|
||||
if (this._initialDelayTimeoutId != 0)
|
||||
@ -560,10 +573,10 @@ var SwitcherList = GObject.registerClass({
|
||||
let leftPadding = this.get_theme_node().get_padding(St.Side.LEFT);
|
||||
let rightPadding = this.get_theme_node().get_padding(St.Side.RIGHT);
|
||||
|
||||
let [, natScrollViewWidth] = this._scrollView.get_preferred_width(height);
|
||||
let [minListWidth] = this._list.get_preferred_width(height);
|
||||
|
||||
let childBox = new Clutter.ActorBox();
|
||||
let scrollable = natScrollViewWidth > width;
|
||||
let scrollable = minListWidth > width;
|
||||
|
||||
this._scrollView.allocate(contentBox, flags);
|
||||
|
||||
|
@ -700,16 +700,17 @@ var WindowManager = class {
|
||||
constructor() {
|
||||
this._shellwm = global.window_manager;
|
||||
|
||||
this._minimizing = [];
|
||||
this._unminimizing = [];
|
||||
this._mapping = [];
|
||||
this._resizing = [];
|
||||
this._destroying = [];
|
||||
this._minimizing = new Set();
|
||||
this._unminimizing = new Set();
|
||||
this._mapping = new Set();
|
||||
this._resizing = new Set();
|
||||
this._resizePending = new Set();
|
||||
this._destroying = new Set();
|
||||
this._movingWindow = null;
|
||||
|
||||
this._dimmedWindows = [];
|
||||
|
||||
this._skippedActors = [];
|
||||
this._skippedActors = new Set();
|
||||
|
||||
this._allowedKeybindings = {};
|
||||
|
||||
@ -1257,7 +1258,7 @@ var WindowManager = class {
|
||||
}
|
||||
|
||||
skipNextEffect(actor) {
|
||||
this._skippedActors.push(actor);
|
||||
this._skippedActors.add(actor);
|
||||
}
|
||||
|
||||
setCustomKeybindingHandler(name, modes, handler) {
|
||||
@ -1286,7 +1287,7 @@ var WindowManager = class {
|
||||
}
|
||||
|
||||
_shouldAnimateActor(actor, types) {
|
||||
if (this._removeEffect(this._skippedActors, actor))
|
||||
if (this._skippedActors.delete(actor))
|
||||
return false;
|
||||
|
||||
if (!this._shouldAnimate())
|
||||
@ -1299,15 +1300,6 @@ var WindowManager = class {
|
||||
return types.includes(type);
|
||||
}
|
||||
|
||||
_removeEffect(list, actor) {
|
||||
let idx = list.indexOf(actor);
|
||||
if (idx != -1) {
|
||||
list.splice(idx, 1);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
_minimizeWindow(shellwm, actor) {
|
||||
let types = [Meta.WindowType.NORMAL,
|
||||
Meta.WindowType.MODAL_DIALOG,
|
||||
@ -1319,7 +1311,7 @@ var WindowManager = class {
|
||||
|
||||
actor.set_scale(1.0, 1.0);
|
||||
|
||||
this._minimizing.push(actor);
|
||||
this._minimizing.add(actor);
|
||||
|
||||
if (actor.meta_window.is_monitor_sized()) {
|
||||
actor.ease({
|
||||
@ -1373,7 +1365,7 @@ var WindowManager = class {
|
||||
}
|
||||
|
||||
_minimizeWindowDone(shellwm, actor) {
|
||||
if (this._removeEffect(this._minimizing, actor)) {
|
||||
if (this._minimizing.delete(actor)) {
|
||||
actor.remove_all_transitions();
|
||||
actor.set_scale(1.0, 1.0);
|
||||
actor.set_opacity(255);
|
||||
@ -1384,7 +1376,7 @@ var WindowManager = class {
|
||||
}
|
||||
|
||||
_minimizeWindowOverwritten(shellwm, actor) {
|
||||
if (this._removeEffect(this._minimizing, actor)) {
|
||||
if (this._minimizing.delete(actor)) {
|
||||
shellwm.completed_minimize(actor);
|
||||
}
|
||||
}
|
||||
@ -1398,7 +1390,7 @@ var WindowManager = class {
|
||||
return;
|
||||
}
|
||||
|
||||
this._unminimizing.push(actor);
|
||||
this._unminimizing.add(actor);
|
||||
|
||||
if (actor.meta_window.is_monitor_sized()) {
|
||||
actor.opacity = 0;
|
||||
@ -1455,7 +1447,7 @@ var WindowManager = class {
|
||||
}
|
||||
|
||||
_unminimizeWindowDone(shellwm, actor) {
|
||||
if (this._removeEffect(this._unminimizing, actor)) {
|
||||
if (this._unminimizing.delete(actor)) {
|
||||
actor.remove_all_transitions();
|
||||
actor.set_scale(1.0, 1.0);
|
||||
actor.set_opacity(255);
|
||||
@ -1466,7 +1458,7 @@ var WindowManager = class {
|
||||
}
|
||||
|
||||
_unminimizeWindowOverwritten(shellwm, actor) {
|
||||
if (this._removeEffect(this._unminimizing, actor)) {
|
||||
if (this._unminimizing.delete(actor)) {
|
||||
shellwm.completed_unminimize(actor);
|
||||
}
|
||||
}
|
||||
@ -1501,6 +1493,7 @@ var WindowManager = class {
|
||||
this._clearAnimationInfo(actor);
|
||||
});
|
||||
|
||||
this._resizePending.add(actor);
|
||||
actor.__animationInfo = { clone: actorClone,
|
||||
oldRect: oldFrameRect,
|
||||
destroyId: destroyId };
|
||||
@ -1509,7 +1502,7 @@ var WindowManager = class {
|
||||
_sizeChangedWindow(shellwm, actor) {
|
||||
if (!actor.__animationInfo)
|
||||
return;
|
||||
if (this._resizing.includes(actor))
|
||||
if (this._resizing.has(actor))
|
||||
return;
|
||||
|
||||
let actorClone = actor.__animationInfo.clone;
|
||||
@ -1519,7 +1512,8 @@ var WindowManager = class {
|
||||
let scaleX = targetRect.width / sourceRect.width;
|
||||
let scaleY = targetRect.height / sourceRect.height;
|
||||
|
||||
this._resizing.push(actor);
|
||||
this._resizePending.delete(actor);
|
||||
this._resizing.add(actor);
|
||||
|
||||
// Now scale and fade out the clone
|
||||
actorClone.ease({
|
||||
@ -1572,7 +1566,7 @@ var WindowManager = class {
|
||||
}
|
||||
|
||||
_sizeChangeWindowDone(shellwm, actor) {
|
||||
if (this._removeEffect(this._resizing, actor)) {
|
||||
if (this._resizing.delete(actor)) {
|
||||
actor.remove_all_transitions();
|
||||
actor.scale_x = 1.0;
|
||||
actor.scale_y = 1.0;
|
||||
@ -1580,10 +1574,13 @@ var WindowManager = class {
|
||||
actor.translation_y = 0;
|
||||
this._clearAnimationInfo(actor);
|
||||
}
|
||||
|
||||
if (this._resizePending.delete(actor))
|
||||
this._shellwm.completed_size_change(actor);
|
||||
}
|
||||
|
||||
_sizeChangeWindowOverwritten(shellwm, actor) {
|
||||
if (this._removeEffect(this._resizing, actor))
|
||||
if (this._resizing.delete(actor))
|
||||
this._clearAnimationInfo(actor);
|
||||
}
|
||||
|
||||
@ -1676,7 +1673,7 @@ var WindowManager = class {
|
||||
actor.scale_y = 0.05;
|
||||
actor.opacity = 0;
|
||||
actor.show();
|
||||
this._mapping.push(actor);
|
||||
this._mapping.add(actor);
|
||||
|
||||
actor.ease({
|
||||
opacity: 255,
|
||||
@ -1698,7 +1695,7 @@ var WindowManager = class {
|
||||
actor.scale_y = 0;
|
||||
actor.opacity = 0;
|
||||
actor.show();
|
||||
this._mapping.push(actor);
|
||||
this._mapping.add(actor);
|
||||
|
||||
actor.ease({
|
||||
opacity: 255,
|
||||
@ -1720,7 +1717,7 @@ var WindowManager = class {
|
||||
}
|
||||
|
||||
_mapWindowDone(shellwm, actor) {
|
||||
if (this._removeEffect(this._mapping, actor)) {
|
||||
if (this._mapping.delete(actor)) {
|
||||
actor.remove_all_transitions();
|
||||
actor.opacity = 255;
|
||||
actor.set_pivot_point(0, 0);
|
||||
@ -1733,7 +1730,7 @@ var WindowManager = class {
|
||||
}
|
||||
|
||||
_mapWindowOverwrite(shellwm, actor) {
|
||||
if (this._removeEffect(this._mapping, actor)) {
|
||||
if (this._mapping.delete(actor)) {
|
||||
shellwm.completed_map(actor);
|
||||
}
|
||||
}
|
||||
@ -1763,7 +1760,7 @@ var WindowManager = class {
|
||||
switch (actor.meta_window.window_type) {
|
||||
case Meta.WindowType.NORMAL:
|
||||
actor.set_pivot_point(0.5, 0.5);
|
||||
this._destroying.push(actor);
|
||||
this._destroying.add(actor);
|
||||
|
||||
actor.ease({
|
||||
opacity: 0,
|
||||
@ -1777,7 +1774,7 @@ var WindowManager = class {
|
||||
case Meta.WindowType.MODAL_DIALOG:
|
||||
case Meta.WindowType.DIALOG:
|
||||
actor.set_pivot_point(0.5, 0.5);
|
||||
this._destroying.push(actor);
|
||||
this._destroying.add(actor);
|
||||
|
||||
if (window.is_attached_dialog()) {
|
||||
let parent = window.get_transient_for();
|
||||
@ -1800,7 +1797,7 @@ var WindowManager = class {
|
||||
}
|
||||
|
||||
_destroyWindowDone(shellwm, actor) {
|
||||
if (this._removeEffect(this._destroying, actor)) {
|
||||
if (this._destroying.delete(actor)) {
|
||||
let parent = actor.get_meta_window().get_transient_for();
|
||||
if (parent && actor._parentDestroyId) {
|
||||
parent.disconnect(actor._parentDestroyId);
|
||||
|
@ -157,6 +157,8 @@ var WindowClone = GObject.registerClass({
|
||||
this.x = this._boundingBox.x;
|
||||
this.y = this._boundingBox.y;
|
||||
|
||||
this._computeWindowCenter();
|
||||
|
||||
let clickAction = new Clutter.ClickAction();
|
||||
clickAction.connect('clicked', this._onClicked.bind(this));
|
||||
clickAction.connect('long-press', this._onLongPress.bind(this));
|
||||
@ -299,6 +301,18 @@ var WindowClone = GObject.registerClass({
|
||||
this.layout_manager.boundingBox = rect;
|
||||
}
|
||||
|
||||
get windowCenter() {
|
||||
return this._windowCenter;
|
||||
}
|
||||
|
||||
_computeWindowCenter() {
|
||||
let box = this.realWindow.get_allocation_box();
|
||||
this._windowCenter = new Clutter.Point({
|
||||
x: box.get_x() + box.get_width() / 2,
|
||||
y: box.get_y() + box.get_height() / 2,
|
||||
});
|
||||
}
|
||||
|
||||
// Find the actor just below us, respecting reparenting done by DND code
|
||||
getActualStackAbove() {
|
||||
if (this._stackAbove == null)
|
||||
@ -1003,11 +1017,7 @@ var UnalignedLayoutStrategy = class extends LayoutStrategy {
|
||||
_sortRow(row) {
|
||||
// Sort windows horizontally to minimize travel distance.
|
||||
// This affects in what order the windows end up in a row.
|
||||
row.windows.sort((a, b) => {
|
||||
let aCenter = a.realWindow.x + a.realWindow.width / 2;
|
||||
let bCenter = b.realWindow.x + b.realWindow.width / 2;
|
||||
return aCenter - bCenter;
|
||||
});
|
||||
row.windows.sort((a, b) => a.windowCenter.x - b.windowCenter.x);
|
||||
}
|
||||
|
||||
computeLayout(windows, layout) {
|
||||
@ -1026,11 +1036,7 @@ var UnalignedLayoutStrategy = class extends LayoutStrategy {
|
||||
// Sort windows vertically to minimize travel distance.
|
||||
// This affects what rows the windows get placed in.
|
||||
let sortedWindows = windows.slice();
|
||||
sortedWindows.sort((a, b) => {
|
||||
let aCenter = a.realWindow.y + a.realWindow.height / 2;
|
||||
let bCenter = b.realWindow.y + b.realWindow.height / 2;
|
||||
return aCenter - bCenter;
|
||||
});
|
||||
sortedWindows.sort((a, b) => a.windowCenter.y - b.windowCenter.y);
|
||||
|
||||
let windowIdx = 0;
|
||||
for (let i = 0; i < numRows; i++) {
|
||||
|
13
meson.build
13
meson.build
@ -1,5 +1,5 @@
|
||||
project('gnome-shell', 'c',
|
||||
version: '3.34.1',
|
||||
version: '3.34.5',
|
||||
meson_version: '>= 0.47.0',
|
||||
license: 'GPLv2+'
|
||||
)
|
||||
@ -31,6 +31,7 @@ polkit_req = '>= 0.100'
|
||||
schemas_req = '>= 3.33.1'
|
||||
startup_req = '>= 0.11'
|
||||
ibus_req = '>= 1.5.2'
|
||||
gnome_desktop_req = '>= 3.32'
|
||||
|
||||
bt_req = '>= 3.9.0'
|
||||
gst_req = '>= 0.11.92'
|
||||
@ -97,6 +98,7 @@ startup_dep = dependency('libstartup-notification-1.0', version: startup_req)
|
||||
ibus_dep = dependency('ibus-1.0', version: ibus_req)
|
||||
x11_dep = dependency('x11')
|
||||
schemas_dep = dependency('gsettings-desktop-schemas', version: schemas_req)
|
||||
gnome_desktop_dep = dependency('gnome-desktop-3.0', version: gnome_desktop_req)
|
||||
|
||||
bt_dep = dependency('gnome-bluetooth-1.0', version: bt_req, required: false)
|
||||
gst_dep = dependency('gstreamer-1.0', version: gst_req, required: false)
|
||||
@ -113,12 +115,8 @@ if get_option('networkmanager')
|
||||
nm_deps += dependency('libnm', version: nm_req)
|
||||
nm_deps += dependency('libsecret-1', version: secret_req)
|
||||
|
||||
vpndir = nm_deps[0].get_pkgconfig_variable('vpnservicedir')
|
||||
|
||||
have_networkmanager = true
|
||||
else
|
||||
vpndir = prefix
|
||||
|
||||
have_networkmanager = false
|
||||
endif
|
||||
|
||||
@ -177,6 +175,11 @@ cdata.set('HAVE__NL_TIME_FIRST_WEEKDAY',
|
||||
cc.has_header_symbol('langinfo.h', '_NL_TIME_FIRST_WEEKDAY')
|
||||
)
|
||||
|
||||
# New API added in gnome-desktop3 3.34.2/3.35.2
|
||||
cdata.set('HAVE_GNOME_SYSTEMD',
|
||||
cc.has_header('libgnome-desktop/gnome-systemd.h', dependencies: gnome_desktop_dep)
|
||||
)
|
||||
|
||||
cdata.set('HAVE_FDWALK',
|
||||
cc.has_function('fdwalk')
|
||||
)
|
||||
|
@ -10,6 +10,7 @@ bn_IN
|
||||
bs
|
||||
ca
|
||||
ca@valencia
|
||||
ckb
|
||||
cs
|
||||
da
|
||||
de
|
||||
|
462
po/pt_BR.po
462
po/pt_BR.po
File diff suppressed because it is too large
Load Diff
1403
po/zh_TW.po
1403
po/zh_TW.po
File diff suppressed because it is too large
Load Diff
@ -105,7 +105,8 @@ typedef struct
|
||||
} CollectAppointmentsData;
|
||||
|
||||
static time_t
|
||||
get_time_from_property (ICalComponent *icomp,
|
||||
get_time_from_property (ECalClient *cal,
|
||||
ICalComponent *icomp,
|
||||
ICalPropertyKind prop_kind,
|
||||
ICalTime * (* get_prop_func) (ICalProperty *prop),
|
||||
ICalTimezone *default_zone)
|
||||
@ -124,12 +125,14 @@ get_time_from_property (ICalComponent *icomp,
|
||||
|
||||
param = i_cal_property_get_first_parameter (prop, I_CAL_TZID_PARAMETER);
|
||||
if (param)
|
||||
timezone = i_cal_timezone_get_builtin_timezone_from_tzid (i_cal_parameter_get_tzid (param));
|
||||
timezone = e_timezone_cache_get_timezone (E_TIMEZONE_CACHE (cal), i_cal_parameter_get_tzid (param));
|
||||
else if (i_cal_time_is_utc (itt))
|
||||
timezone = i_cal_timezone_get_utc_timezone ();
|
||||
else
|
||||
timezone = default_zone;
|
||||
|
||||
i_cal_time_set_timezone (itt, timezone);
|
||||
|
||||
retval = i_cal_time_as_timet_with_zone (itt, timezone);
|
||||
|
||||
g_clear_object (¶m);
|
||||
@ -180,27 +183,32 @@ get_ical_description (ICalComponent *icomp)
|
||||
}
|
||||
|
||||
static inline time_t
|
||||
get_ical_start_time (ICalComponent *icomp,
|
||||
get_ical_start_time (ECalClient *cal,
|
||||
ICalComponent *icomp,
|
||||
ICalTimezone *default_zone)
|
||||
{
|
||||
return get_time_from_property (icomp,
|
||||
return get_time_from_property (cal,
|
||||
icomp,
|
||||
I_CAL_DTSTART_PROPERTY,
|
||||
i_cal_property_get_dtstart,
|
||||
default_zone);
|
||||
}
|
||||
|
||||
static inline time_t
|
||||
get_ical_end_time (ICalComponent *icomp,
|
||||
get_ical_end_time (ECalClient *cal,
|
||||
ICalComponent *icomp,
|
||||
ICalTimezone *default_zone)
|
||||
{
|
||||
return get_time_from_property (icomp,
|
||||
return get_time_from_property (cal,
|
||||
icomp,
|
||||
I_CAL_DTEND_PROPERTY,
|
||||
i_cal_property_get_dtend,
|
||||
default_zone);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
get_ical_is_all_day (ICalComponent *icomp,
|
||||
get_ical_is_all_day (ECalClient *cal,
|
||||
ICalComponent *icomp,
|
||||
time_t start_time,
|
||||
ICalTimezone *default_zone)
|
||||
{
|
||||
@ -226,7 +234,7 @@ get_ical_is_all_day (ICalComponent *icomp,
|
||||
start_tm->tm_hour != 0)
|
||||
return FALSE;
|
||||
|
||||
if ((end_time = get_ical_end_time (icomp, default_zone)))
|
||||
if ((end_time = get_ical_end_time (cal, icomp, default_zone)))
|
||||
return (end_time - start_time) % 86400 == 0;
|
||||
|
||||
prop = i_cal_component_get_first_property (icomp, I_CAL_DURATION_PROPERTY);
|
||||
@ -244,20 +252,24 @@ get_ical_is_all_day (ICalComponent *icomp,
|
||||
}
|
||||
|
||||
static inline time_t
|
||||
get_ical_due_time (ICalComponent *icomp,
|
||||
get_ical_due_time (ECalClient *cal,
|
||||
ICalComponent *icomp,
|
||||
ICalTimezone *default_zone)
|
||||
{
|
||||
return get_time_from_property (icomp,
|
||||
return get_time_from_property (cal,
|
||||
icomp,
|
||||
I_CAL_DUE_PROPERTY,
|
||||
i_cal_property_get_due,
|
||||
default_zone);
|
||||
}
|
||||
|
||||
static inline time_t
|
||||
get_ical_completed_time (ICalComponent *icomp,
|
||||
get_ical_completed_time (ECalClient *cal,
|
||||
ICalComponent *icomp,
|
||||
ICalTimezone *default_zone)
|
||||
{
|
||||
return get_time_from_property (icomp,
|
||||
return get_time_from_property (cal,
|
||||
icomp,
|
||||
I_CAL_COMPLETED_PROPERTY,
|
||||
i_cal_property_get_completed,
|
||||
default_zone);
|
||||
@ -411,9 +423,10 @@ calendar_appointment_init (CalendarAppointment *appointment,
|
||||
appointment->summary = get_ical_summary (icomp);
|
||||
appointment->description = get_ical_description (icomp);
|
||||
appointment->color_string = get_source_color (cal);
|
||||
appointment->start_time = get_ical_start_time (icomp, default_zone);
|
||||
appointment->end_time = get_ical_end_time (icomp, default_zone);
|
||||
appointment->is_all_day = get_ical_is_all_day (icomp,
|
||||
appointment->start_time = get_ical_start_time (cal, icomp, default_zone);
|
||||
appointment->end_time = get_ical_end_time (cal, icomp, default_zone);
|
||||
appointment->is_all_day = get_ical_is_all_day (cal,
|
||||
icomp,
|
||||
appointment->start_time,
|
||||
default_zone);
|
||||
}
|
||||
@ -430,6 +443,18 @@ calendar_appointment_new (ICalComponent *icomp,
|
||||
return appointment;
|
||||
}
|
||||
|
||||
static time_t
|
||||
timet_from_ical_time (ICalTime *time,
|
||||
ICalTimezone *default_zone)
|
||||
{
|
||||
ICalTimezone *timezone = NULL;
|
||||
|
||||
timezone = i_cal_time_get_timezone (time);
|
||||
if (timezone == NULL)
|
||||
timezone = default_zone;
|
||||
return i_cal_time_as_timet_with_zone (time, timezone);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
generate_instances_cb (ICalComponent *icomp,
|
||||
ICalTime *instance_start,
|
||||
@ -456,8 +481,8 @@ generate_instances_cb (ICalComponent *icomp,
|
||||
}
|
||||
|
||||
occurrence = g_new0 (CalendarOccurrence, 1);
|
||||
occurrence->start_time = i_cal_time_as_timet_with_zone (instance_start, default_zone);
|
||||
occurrence->end_time = i_cal_time_as_timet_with_zone (instance_end, default_zone);
|
||||
occurrence->start_time = timet_from_ical_time (instance_start, default_zone);
|
||||
occurrence->end_time = timet_from_ical_time (instance_end, default_zone);
|
||||
occurrence->rid = e_cal_util_component_get_recurid_as_string (icomp);
|
||||
|
||||
appointment->occurrences = g_slist_append (appointment->occurrences, occurrence);
|
||||
|
@ -142,9 +142,10 @@ settings_list_remove (GSettings *settings,
|
||||
|
||||
n_values = g_strv_length (list);
|
||||
new_value = g_new0 (char *, n_values);
|
||||
for (i = 0, s = (const char **)list; i < n_values; i++, s++)
|
||||
i = 0;
|
||||
for (s = (const char **)list; *s != NULL; s++)
|
||||
if (!g_str_equal (*s, value))
|
||||
new_value[i] = g_strdup (*s);
|
||||
new_value[i++] = g_strdup (*s);
|
||||
|
||||
g_settings_set_strv (settings, key, (const char **)new_value);
|
||||
g_settings_sync ();
|
||||
|
@ -192,7 +192,7 @@ libshell_no_gir_sources += dbus_generated
|
||||
|
||||
libshell = library('gnome-shell',
|
||||
sources: libshell_gir_sources + libshell_no_gir_sources,
|
||||
dependencies: gnome_shell_deps + [libshell_menu_dep, libst_dep, mutter_dep, m_dep],
|
||||
dependencies: gnome_shell_deps + [libshell_menu_dep, libst_dep, mutter_dep, gnome_desktop_dep, m_dep],
|
||||
include_directories: [conf_inc, st_inc, include_directories('tray')],
|
||||
c_args: gnome_shell_cflags,
|
||||
link_with: [libtray],
|
||||
|
@ -29,6 +29,11 @@
|
||||
#include <meta/meta-workspace-manager.h>
|
||||
#include <meta/meta-x11-display.h>
|
||||
|
||||
#ifdef HAVE_GNOME_SYSTEMD
|
||||
#define GNOME_DESKTOP_USE_UNSTABLE_API
|
||||
#include <libgnome-desktop/gnome-systemd.h>
|
||||
#endif
|
||||
|
||||
/* Memory report bits */
|
||||
#ifdef HAVE_MALLINFO
|
||||
#include <malloc.h>
|
||||
@ -43,6 +48,7 @@
|
||||
#include "shell-perf-log.h"
|
||||
#include "shell-window-tracker.h"
|
||||
#include "shell-wm.h"
|
||||
#include "shell-util.h"
|
||||
#include "st.h"
|
||||
|
||||
static ShellGlobal *the_object = NULL;
|
||||
@ -1308,6 +1314,32 @@ shell_global_get_current_time (ShellGlobal *global)
|
||||
return clutter_get_current_event_time ();
|
||||
}
|
||||
|
||||
#ifdef HAVE_GNOME_SYSTEMD
|
||||
static void
|
||||
shell_global_app_launched_cb (GAppLaunchContext *context,
|
||||
GAppInfo *info,
|
||||
GVariant *platform_data,
|
||||
gpointer user_data)
|
||||
{
|
||||
gint32 pid;
|
||||
const gchar *app_name;
|
||||
|
||||
if (!g_variant_lookup (platform_data, "pid", "i", &pid))
|
||||
return;
|
||||
|
||||
app_name = g_app_info_get_id (info);
|
||||
if (app_name == NULL)
|
||||
app_name = g_app_info_get_executable (info);
|
||||
|
||||
/* Start async request; we don't care about the result */
|
||||
gnome_start_systemd_scope (app_name,
|
||||
pid,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL, NULL, NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* shell_global_create_app_launch_context:
|
||||
* @global: A #ShellGlobal
|
||||
@ -1343,6 +1375,13 @@ shell_global_create_app_launch_context (ShellGlobal *global,
|
||||
|
||||
meta_launch_context_set_workspace (context, ws);
|
||||
|
||||
#ifdef HAVE_GNOME_SYSTEMD
|
||||
g_signal_connect (context,
|
||||
"launched",
|
||||
G_CALLBACK (shell_global_app_launched_cb),
|
||||
NULL);
|
||||
#endif
|
||||
|
||||
return (GAppLaunchContext *) context;
|
||||
}
|
||||
|
||||
@ -1515,6 +1554,55 @@ delete_variant_cb (GObject *object,
|
||||
g_hash_table_remove (global->save_ops, object);
|
||||
}
|
||||
|
||||
static void
|
||||
replace_contents_worker (GTask *task,
|
||||
gpointer source_object,
|
||||
gpointer task_data,
|
||||
GCancellable *cancellable)
|
||||
{
|
||||
GFile *file = source_object;
|
||||
GBytes *bytes = task_data;
|
||||
GError *error = NULL;
|
||||
const gchar *data;
|
||||
gsize len;
|
||||
|
||||
data = g_bytes_get_data (bytes, &len);
|
||||
|
||||
if (!g_file_replace_contents (file, data, len, NULL, FALSE,
|
||||
G_FILE_CREATE_REPLACE_DESTINATION,
|
||||
NULL, cancellable, &error))
|
||||
g_task_return_error (task, g_steal_pointer (&error));
|
||||
else
|
||||
g_task_return_boolean (task, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
replace_contents_async (GFile *path,
|
||||
GBytes *bytes,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
g_autoptr(GTask) task = NULL;
|
||||
|
||||
g_assert (G_IS_FILE (path));
|
||||
g_assert (bytes != NULL);
|
||||
g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
|
||||
|
||||
task = g_task_new (path, cancellable, callback, user_data);
|
||||
g_task_set_source_tag (task, replace_contents_async);
|
||||
g_task_set_task_data (task, g_bytes_ref (bytes), (GDestroyNotify)g_bytes_unref);
|
||||
g_task_run_in_thread (task, replace_contents_worker);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
replace_contents_finish (GFile *file,
|
||||
GAsyncResult *result,
|
||||
GError **error)
|
||||
{
|
||||
return g_task_propagate_boolean (G_TASK (result), error);
|
||||
}
|
||||
|
||||
static void
|
||||
replace_variant_cb (GObject *object,
|
||||
GAsyncResult *result,
|
||||
@ -1523,7 +1611,7 @@ replace_variant_cb (GObject *object,
|
||||
ShellGlobal *global = user_data;
|
||||
GError *error = NULL;
|
||||
|
||||
if (!g_file_replace_contents_finish (G_FILE (object), result, NULL, &error))
|
||||
if (!replace_contents_finish (G_FILE (object), result, &error))
|
||||
{
|
||||
if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
||||
{
|
||||
@ -1559,12 +1647,19 @@ save_variant (ShellGlobal *global,
|
||||
}
|
||||
else
|
||||
{
|
||||
g_file_replace_contents_async (path,
|
||||
g_variant_get_data (variant),
|
||||
g_variant_get_size (variant),
|
||||
NULL, FALSE,
|
||||
G_FILE_CREATE_REPLACE_DESTINATION,
|
||||
cancellable, replace_variant_cb, global);
|
||||
g_autoptr(GBytes) bytes = NULL;
|
||||
|
||||
bytes = g_bytes_new_with_free_func (g_variant_get_data (variant),
|
||||
g_variant_get_size (variant),
|
||||
(GDestroyNotify)g_variant_unref,
|
||||
g_variant_ref (variant));
|
||||
/* g_file_replace_contents_async() can potentially fsync() from the
|
||||
* calling thread when completing the asynchronous task. Instead, we
|
||||
* want to force that fsync() to a thread to avoid blocking the
|
||||
* compositor main loop. Using our own replace_contents_async()
|
||||
* simply executes the operation synchronously from a thread.
|
||||
*/
|
||||
replace_contents_async (path, bytes, cancellable, replace_variant_cb, global);
|
||||
}
|
||||
|
||||
g_object_unref (path);
|
||||
|
@ -478,6 +478,63 @@ shell_network_agent_respond (ShellNetworkAgent *self,
|
||||
g_hash_table_remove (priv->requests, request_id);
|
||||
}
|
||||
|
||||
static void
|
||||
search_vpn_plugin (GTask *task,
|
||||
gpointer object,
|
||||
gpointer task_data,
|
||||
GCancellable *cancellable)
|
||||
{
|
||||
NMVpnPluginInfo *info = NULL;
|
||||
char *service = task_data;
|
||||
|
||||
info = nm_vpn_plugin_info_new_search_file (NULL, service);
|
||||
|
||||
if (info)
|
||||
{
|
||||
g_task_return_pointer (task, info, g_object_unref);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_task_return_new_error (task,
|
||||
G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
|
||||
"No plugin for %s", service);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
shell_network_agent_search_vpn_plugin (ShellNetworkAgent *self,
|
||||
const char *service,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
g_autoptr(GTask) task = NULL;
|
||||
|
||||
g_return_if_fail (SHELL_IS_NETWORK_AGENT (self));
|
||||
g_return_if_fail (service != NULL);
|
||||
|
||||
task = g_task_new (self, NULL, callback, user_data);
|
||||
g_task_set_source_tag (task, shell_network_agent_search_vpn_plugin);
|
||||
g_task_set_task_data (task, g_strdup (service), g_free);
|
||||
|
||||
g_task_run_in_thread (task, search_vpn_plugin);
|
||||
}
|
||||
|
||||
/**
|
||||
* shell_network_agent_search_vpn_plugin_finish:
|
||||
*
|
||||
* Returns: (nullable) (transfer full): The found plugin or %NULL
|
||||
*/
|
||||
NMVpnPluginInfo *
|
||||
shell_network_agent_search_vpn_plugin_finish (ShellNetworkAgent *self,
|
||||
GAsyncResult *result,
|
||||
GError **error)
|
||||
{
|
||||
g_return_val_if_fail (SHELL_IS_NETWORK_AGENT (self), NULL);
|
||||
g_return_val_if_fail (G_IS_TASK (result), NULL);
|
||||
|
||||
return g_task_propagate_pointer (G_TASK (result), error);
|
||||
}
|
||||
|
||||
static void
|
||||
shell_network_agent_cancel_get_secrets (NMSecretAgentOld *agent,
|
||||
const gchar *connection_path,
|
||||
|
@ -51,6 +51,14 @@ void shell_network_agent_respond (ShellNetworkAgent *self,
|
||||
gchar *request_id,
|
||||
ShellNetworkAgentResponse response);
|
||||
|
||||
void shell_network_agent_search_vpn_plugin (ShellNetworkAgent *self,
|
||||
const char *service,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
NMVpnPluginInfo *shell_network_agent_search_vpn_plugin_finish (ShellNetworkAgent *self,
|
||||
GAsyncResult *result,
|
||||
GError **error);
|
||||
|
||||
/* If these are kept in sync with nm-applet, secrets will be shared */
|
||||
#define SHELL_KEYRING_UUID_TAG "connection-uuid"
|
||||
#define SHELL_KEYRING_SN_TAG "setting-name"
|
||||
|
@ -146,7 +146,7 @@ G_DEFINE_TYPE(ShellRecorder, shell_recorder, G_TYPE_OBJECT);
|
||||
|
||||
/* The default pipeline.
|
||||
*/
|
||||
#define DEFAULT_PIPELINE "vp9enc min_quantizer=13 max_quantizer=13 cpu-used=5 deadline=1000000 threads=%T ! queue ! webmmux"
|
||||
#define DEFAULT_PIPELINE "vp8enc min_quantizer=13 max_quantizer=13 cpu-used=5 deadline=1000000 threads=%T ! queue ! webmmux"
|
||||
|
||||
/* If we can find the amount of memory on the machine, we use half
|
||||
* of that for memory_target, otherwise, we use this value, in kB.
|
||||
@ -1479,7 +1479,7 @@ shell_recorder_set_draw_cursor (ShellRecorder *recorder,
|
||||
* might be used to send the output to an icecast server
|
||||
* via shout2send or similar.
|
||||
*
|
||||
* The default value is 'vp9enc min_quantizer=13 max_quantizer=13 cpu-used=5 deadline=1000000 threads=%T ! queue ! webmmux'
|
||||
* The default value is 'vp8enc min_quantizer=13 max_quantizer=13 cpu-used=5 deadline=1000000 threads=%T ! queue ! webmmux'
|
||||
*/
|
||||
void
|
||||
shell_recorder_set_pipeline (ShellRecorder *recorder,
|
||||
|
@ -457,7 +457,6 @@ grab_window_screenshot (ClutterActor *stage,
|
||||
ClutterActor *window_actor;
|
||||
gfloat actor_x, actor_y;
|
||||
MetaRectangle rect;
|
||||
cairo_rectangle_int_t clip;
|
||||
|
||||
window_actor = CLUTTER_ACTOR (meta_window_get_compositor_private (window));
|
||||
clutter_actor_get_position (window_actor, &actor_x, &actor_y);
|
||||
@ -467,16 +466,10 @@ grab_window_screenshot (ClutterActor *stage,
|
||||
if (!priv->include_frame)
|
||||
meta_window_frame_rect_to_client_rect (window, &rect, &rect);
|
||||
|
||||
priv->screenshot_area.x = rect.x;
|
||||
priv->screenshot_area.y = rect.y;
|
||||
clip.x = rect.x - (gint) actor_x;
|
||||
clip.y = rect.y - (gint) actor_y;
|
||||
|
||||
clip.width = priv->screenshot_area.width = rect.width;
|
||||
clip.height = priv->screenshot_area.height = rect.height;
|
||||
priv->screenshot_area = rect;
|
||||
|
||||
priv->image = meta_window_actor_get_image (META_WINDOW_ACTOR (window_actor),
|
||||
&clip);
|
||||
NULL);
|
||||
priv->datetime = g_date_time_new_now_local ();
|
||||
|
||||
if (priv->include_cursor)
|
||||
|
@ -43,6 +43,8 @@ struct _StTextureCachePrivate
|
||||
GHashTable *keyed_cache; /* char * -> ClutterImage* */
|
||||
GHashTable *keyed_surface_cache; /* char * -> cairo_surface_t* */
|
||||
|
||||
GHashTable *used_scales; /* Set: double */
|
||||
|
||||
/* Presently this is used to de-duplicate requests for GIcons and async URIs. */
|
||||
GHashTable *outstanding_requests; /* char * -> AsyncTextureLoadData * */
|
||||
|
||||
@ -181,6 +183,7 @@ st_texture_cache_init (StTextureCache *self)
|
||||
g_str_equal,
|
||||
g_free,
|
||||
(GDestroyNotify) cairo_surface_destroy);
|
||||
self->priv->used_scales = g_hash_table_new (g_double_hash, g_double_equal);
|
||||
self->priv->outstanding_requests = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||
g_free, NULL);
|
||||
self->priv->file_monitors = g_hash_table_new_full (g_file_hash, (GEqualFunc) g_file_equal,
|
||||
@ -199,6 +202,7 @@ st_texture_cache_dispose (GObject *object)
|
||||
|
||||
g_clear_pointer (&self->priv->keyed_cache, g_hash_table_destroy);
|
||||
g_clear_pointer (&self->priv->keyed_surface_cache, g_hash_table_destroy);
|
||||
g_clear_pointer (&self->priv->used_scales, g_hash_table_destroy);
|
||||
g_clear_pointer (&self->priv->outstanding_requests, g_hash_table_destroy);
|
||||
g_clear_pointer (&self->priv->file_monitors, g_hash_table_destroy);
|
||||
|
||||
@ -1062,6 +1066,22 @@ load_from_pixbuf (GdkPixbuf *pixbuf,
|
||||
return actor;
|
||||
}
|
||||
|
||||
static void
|
||||
hash_table_remove_with_scales (GHashTable *hash,
|
||||
GList *scales,
|
||||
const char *base_key)
|
||||
{
|
||||
GList *l;
|
||||
|
||||
for (l = scales; l; l = l->next)
|
||||
{
|
||||
double scale = *((double *)l->data);
|
||||
g_autofree char *key = NULL;
|
||||
key = g_strdup_printf ("%s%f", base_key, scale);
|
||||
g_hash_table_remove (hash, key);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
file_changed_cb (GFileMonitor *monitor,
|
||||
GFile *file,
|
||||
@ -1072,18 +1092,22 @@ file_changed_cb (GFileMonitor *monitor,
|
||||
StTextureCache *cache = user_data;
|
||||
char *key;
|
||||
guint file_hash;
|
||||
g_autoptr (GList) scales = NULL;
|
||||
|
||||
if (event_type != G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT)
|
||||
return;
|
||||
|
||||
file_hash = g_file_hash (file);
|
||||
scales = g_hash_table_get_keys (cache->priv->used_scales);
|
||||
|
||||
key = g_strdup_printf (CACHE_PREFIX_FILE "%u", file_hash);
|
||||
g_hash_table_remove (cache->priv->keyed_cache, key);
|
||||
hash_table_remove_with_scales (cache->priv->keyed_cache, scales, key);
|
||||
g_free (key);
|
||||
|
||||
key = g_strdup_printf (CACHE_PREFIX_FILE_FOR_CAIRO "%u", file_hash);
|
||||
g_hash_table_remove (cache->priv->keyed_surface_cache, key);
|
||||
hash_table_remove_with_scales (cache->priv->keyed_surface_cache, scales, key);
|
||||
g_free (key);
|
||||
|
||||
g_signal_emit (cache, signals[TEXTURE_FILE_CHANGED], 0, file);
|
||||
@ -1418,7 +1442,10 @@ st_texture_cache_load_file_sync_to_cogl_texture (StTextureCache *cache,
|
||||
goto out;
|
||||
|
||||
if (policy == ST_TEXTURE_CACHE_POLICY_FOREVER)
|
||||
g_hash_table_insert (cache->priv->keyed_cache, g_strdup (key), image);
|
||||
{
|
||||
g_hash_table_insert (cache->priv->keyed_cache, g_strdup (key), image);
|
||||
g_hash_table_insert (cache->priv->used_scales, &resource_scale, &resource_scale);
|
||||
}
|
||||
}
|
||||
|
||||
/* Because the texture is loaded synchronously, we won't call
|
||||
@ -1467,6 +1494,7 @@ st_texture_cache_load_file_sync_to_cairo_surface (StTextureCache *cache,
|
||||
cairo_surface_reference (surface);
|
||||
g_hash_table_insert (cache->priv->keyed_surface_cache,
|
||||
g_strdup (key), surface);
|
||||
g_hash_table_insert (cache->priv->used_scales, &resource_scale, &resource_scale);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 0e1b4bdafc364d5b62ffd14847e9e6ecfefbf2c9
|
||||
Subproject commit ec5cf3e0de6715803e64b65abb059e2155b3d6de
|
Loading…
Reference in New Issue
Block a user