diff --git a/data/theme/gnome-shell-sass/_common.scss b/data/theme/gnome-shell-sass/_common.scss
index df530ede6..f765a0d77 100644
--- a/data/theme/gnome-shell-sass/_common.scss
+++ b/data/theme/gnome-shell-sass/_common.scss
@@ -2047,11 +2047,11 @@ StScrollBar {
//SCREEN SHIELD
-$_screenshield_shadow: 0px 0px 6px rgba(0, 0, 0, 0.726);
+$_unlockdialog_shadow: 0px 0px 6px rgba(0, 0, 0, 0.726);
.unlock-dialog-clock {
color: white;
- text-shadow: $_screenshield_shadow;
+ text-shadow: $_unlockdialog_shadow;
font-weight: bold;
text-align: center;
padding-bottom: 1.5em;
@@ -2059,7 +2059,7 @@ $_screenshield_shadow: 0px 0px 6px rgba(0, 0, 0, 0.726);
.unlock-dialog-clock-time {
font-size: 72pt;
- text-shadow: $_screenshield_shadow;
+ text-shadow: $_unlockdialog_shadow;
font-feature-settings: "tnum";
}
@@ -2068,7 +2068,7 @@ $_screenshield_shadow: 0px 0px 6px rgba(0, 0, 0, 0.726);
font-weight: normal;
}
-.screen-shield-notifications-container {
+.unlock-dialog-notifications-container {
spacing: 6px;
width: 30em;
background-color: transparent;
@@ -2079,7 +2079,7 @@ $_screenshield_shadow: 0px 0px 6px rgba(0, 0, 0, 0.726);
}
.notification,
- .screen-shield-notification-source {
+ .unlock-dialog-notification-source {
padding: 12px 6px;
border: 1px solid $osd_outer_borders_color;
background-color: transparentize($osd_bg_color,0.5);
@@ -2090,12 +2090,12 @@ $_screenshield_shadow: 0px 0px 6px rgba(0, 0, 0, 0.726);
}
-.screen-shield-notification-label {
+.unlock-dialog-notification-label {
font-weight: bold;
padding: 0px 0px 0px 12px;
}
-.screen-shield-notification-count-text { padding: 0px 0px 0px 12px; }
+.unlock-dialog-notification-count-text { padding: 0px 0px 0px 12px; }
#panel.lock-screen { background-color: transparentize($osd_bg_color, 0.5); }
@@ -2109,7 +2109,7 @@ $_screenshield_shadow: 0px 0px 6px rgba(0, 0, 0, 0.726);
background-repeat: repeat;
}
-#screenShieldNotifications {
+#unlockDialogNotifications {
StButton#vhandle, StButton#hhandle {
background-color: transparentize($bg_color,0.7);
&:hover, &:focus { background-color: transparentize($bg_color,0.5); }
diff --git a/js/ui/screenShield.js b/js/ui/screenShield.js
index 38368c3d7..4e9ed3bf1 100644
--- a/js/ui/screenShield.js
+++ b/js/ui/screenShield.js
@@ -1,7 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
-const { AccountsService, Clutter, Gio, GLib,
- GObject, Graphene, Meta, Shell, St } = imports.gi;
+const { AccountsService, Clutter, Gio,
+ GLib, Graphene, Meta, Shell, St } = imports.gi;
const Signals = imports.signals;
const Background = imports.ui.background;
@@ -34,8 +34,6 @@ const BLUR_RADIUS = 200;
// the slide up automatically
var ARROW_DRAG_THRESHOLD = 0.1;
-var SUMMARY_ICON_SIZE = 48;
-
// ScreenShield animation time
// - STANDARD_FADE_TIME is used when the session goes idle
// - MANUAL_FADE_TIME is used for lowering the shield when asked by the user,
@@ -45,264 +43,6 @@ var STANDARD_FADE_TIME = 10000;
var MANUAL_FADE_TIME = 300;
var CURTAIN_SLIDE_TIME = 300;
-var NotificationsBox = GObject.registerClass({
- Signals: { 'wake-up-screen': {} },
-}, class NotificationsBox extends St.BoxLayout {
- _init() {
- super._init({
- vertical: true,
- name: 'screenShieldNotifications',
- style_class: 'screen-shield-notifications-container',
- });
-
- this._scrollView = new St.ScrollView({ hscrollbar_policy: St.PolicyType.NEVER });
- this._notificationBox = new St.BoxLayout({ vertical: true,
- style_class: 'screen-shield-notifications-container' });
- this._scrollView.add_actor(this._notificationBox);
-
- this.add_child(this._scrollView);
-
- this._sources = new Map();
- Main.messageTray.getSources().forEach(source => {
- this._sourceAdded(Main.messageTray, source, true);
- });
- this._updateVisibility();
-
- this._sourceAddedId = Main.messageTray.connect('source-added', this._sourceAdded.bind(this));
-
- this.connect('destroy', this._onDestroy.bind(this));
- }
-
- _onDestroy() {
- if (this._sourceAddedId) {
- Main.messageTray.disconnect(this._sourceAddedId);
- this._sourceAddedId = 0;
- }
-
- let items = this._sources.entries();
- for (let [source, obj] of items)
- this._removeSource(source, obj);
- }
-
- _updateVisibility() {
- this._notificationBox.visible =
- this._notificationBox.get_children().some(a => a.visible);
-
- this.visible = this._notificationBox.visible;
- }
-
- _makeNotificationCountText(count, isChat) {
- if (isChat)
- return ngettext("%d new message", "%d new messages", count).format(count);
- else
- return ngettext("%d new notification", "%d new notifications", count).format(count);
- }
-
- _makeNotificationSource(source, box) {
- let sourceActor = new MessageTray.SourceActor(source, SUMMARY_ICON_SIZE);
- box.add_child(sourceActor);
-
- let textBox = new St.BoxLayout({ vertical: true });
- box.add_child(textBox);
-
- let title = new St.Label({ text: source.title,
- style_class: 'screen-shield-notification-label' });
- textBox.add(title);
-
- let count = source.unseenCount;
- let countLabel = new St.Label({ text: this._makeNotificationCountText(count, source.isChat),
- style_class: 'screen-shield-notification-count-text' });
- textBox.add(countLabel);
-
- box.visible = count != 0;
- return [title, countLabel];
- }
-
- _makeNotificationDetailedSource(source, box) {
- let sourceActor = new MessageTray.SourceActor(source, SUMMARY_ICON_SIZE);
- let sourceBin = new St.Bin({ child: sourceActor });
- box.add(sourceBin);
-
- let textBox = new St.BoxLayout({ vertical: true });
- box.add_child(textBox);
-
- let title = new St.Label({ text: source.title,
- style_class: 'screen-shield-notification-label' });
- textBox.add(title);
-
- let visible = false;
- for (let i = 0; i < source.notifications.length; i++) {
- let n = source.notifications[i];
-
- if (n.acknowledged)
- continue;
-
- let body = '';
- if (n.bannerBodyText) {
- body = n.bannerBodyMarkup
- ? n.bannerBodyText
- : GLib.markup_escape_text(n.bannerBodyText, -1);
- }
-
- let label = new St.Label({ style_class: 'screen-shield-notification-count-text' });
- label.clutter_text.set_markup(`${n.title} ${body}`);
- textBox.add(label);
-
- visible = true;
- }
-
- box.visible = visible;
- return [title, null];
- }
-
- _shouldShowDetails(source) {
- return source.policy.detailsInLockScreen ||
- source.narrowestPrivacyScope == MessageTray.PrivacyScope.SYSTEM;
- }
-
- _showSource(source, obj, box) {
- if (obj.detailed)
- [obj.titleLabel, obj.countLabel] = this._makeNotificationDetailedSource(source, box);
- else
- [obj.titleLabel, obj.countLabel] = this._makeNotificationSource(source, box);
-
- box.visible = obj.visible && (source.unseenCount > 0);
- }
-
- _sourceAdded(tray, source, initial) {
- let obj = {
- visible: source.policy.showInLockScreen,
- detailed: this._shouldShowDetails(source),
- sourceDestroyId: 0,
- sourceCountChangedId: 0,
- sourceTitleChangedId: 0,
- sourceUpdatedId: 0,
- sourceBox: null,
- titleLabel: null,
- countLabel: null,
- };
-
- obj.sourceBox = new St.BoxLayout({ style_class: 'screen-shield-notification-source',
- x_expand: true });
- this._showSource(source, obj, obj.sourceBox);
- this._notificationBox.add_child(obj.sourceBox);
-
- obj.sourceCountChangedId = source.connect('notify::count', () => {
- this._countChanged(source, obj);
- });
- obj.sourceTitleChangedId = source.connect('notify::title', () => {
- this._titleChanged(source, obj);
- });
- obj.policyChangedId = source.policy.connect('notify', (policy, pspec) => {
- if (pspec.name == 'show-in-lock-screen')
- this._visibleChanged(source, obj);
- else
- this._detailedChanged(source, obj);
- });
- obj.sourceDestroyId = source.connect('destroy', () => {
- this._onSourceDestroy(source, obj);
- });
-
- this._sources.set(source, obj);
-
- if (!initial) {
- // block scrollbars while animating, if they're not needed now
- let boxHeight = this._notificationBox.height;
- if (this._scrollView.height >= boxHeight)
- this._scrollView.vscrollbar_policy = St.PolicyType.NEVER;
-
- let widget = obj.sourceBox;
- let [, natHeight] = widget.get_preferred_height(-1);
- widget.height = 0;
- widget.ease({
- height: natHeight,
- mode: Clutter.AnimationMode.EASE_OUT_QUAD,
- duration: 250,
- onComplete: () => {
- this._scrollView.vscrollbar_policy = St.PolicyType.AUTOMATIC;
- widget.set_height(-1);
- },
- });
-
- this._updateVisibility();
- if (obj.sourceBox.visible)
- this.emit('wake-up-screen');
- }
- }
-
- _titleChanged(source, obj) {
- obj.titleLabel.text = source.title;
- }
-
- _countChanged(source, obj) {
- // A change in the number of notifications may change whether we show
- // details.
- let newDetailed = this._shouldShowDetails(source);
- let oldDetailed = obj.detailed;
-
- obj.detailed = newDetailed;
-
- if (obj.detailed || oldDetailed != newDetailed) {
- // A new notification was pushed, or a previous notification was destroyed.
- // Give up, and build the list again.
-
- obj.sourceBox.destroy_all_children();
- obj.titleLabel = obj.countLabel = null;
- this._showSource(source, obj, obj.sourceBox);
- } else {
- let count = source.unseenCount;
- obj.countLabel.text = this._makeNotificationCountText(count, source.isChat);
- }
-
- obj.sourceBox.visible = obj.visible && (source.unseenCount > 0);
-
- this._updateVisibility();
- if (obj.sourceBox.visible)
- this.emit('wake-up-screen');
- }
-
- _visibleChanged(source, obj) {
- if (obj.visible == source.policy.showInLockScreen)
- return;
-
- obj.visible = source.policy.showInLockScreen;
- obj.sourceBox.visible = obj.visible && source.unseenCount > 0;
-
- this._updateVisibility();
- if (obj.sourceBox.visible)
- this.emit('wake-up-screen');
- }
-
- _detailedChanged(source, obj) {
- let newDetailed = this._shouldShowDetails(source);
- if (obj.detailed == newDetailed)
- return;
-
- obj.detailed = newDetailed;
-
- obj.sourceBox.destroy_all_children();
- obj.titleLabel = obj.countLabel = null;
- this._showSource(source, obj, obj.sourceBox);
- }
-
- _onSourceDestroy(source, obj) {
- this._removeSource(source, obj);
- this._updateVisibility();
- }
-
- _removeSource(source, obj) {
- obj.sourceBox.destroy();
- obj.sourceBox = obj.titleLabel = obj.countLabel = null;
-
- source.disconnect(obj.sourceDestroyId);
- source.disconnect(obj.sourceCountChangedId);
- source.disconnect(obj.sourceTitleChangedId);
- source.policy.disconnect(obj.policyChangedId);
-
- this._sources.delete(source);
- }
-});
-
function clamp(value, min, max) {
return Math.max(min, Math.min(max, value));
}
@@ -937,10 +677,6 @@ var ScreenShield = class {
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_child(this._notificationsBox);
-
this._hasLockScreen = true;
}
@@ -950,12 +686,6 @@ var ScreenShield = class {
}
_clearLockScreen() {
- if (this._notificationsBox) {
- this._notificationsBox.disconnect(this._wakeUpScreenId);
- this._notificationsBox.destroy();
- this._notificationsBox = null;
- }
-
this._lockScreenContentsBox.destroy();
this._hasLockScreen = false;
diff --git a/js/ui/unlockDialog.js b/js/ui/unlockDialog.js
index a046c56f6..b142ba2db 100644
--- a/js/ui/unlockDialog.js
+++ b/js/ui/unlockDialog.js
@@ -6,12 +6,273 @@ const { AccountsService, Atk, Clutter, Gdm, Gio,
const Layout = imports.ui.layout;
const Main = imports.ui.main;
+const MessageTray = imports.ui.messageTray;
const AuthPrompt = imports.gdm.authPrompt;
// The timeout before going back automatically to the lock screen (in seconds)
const IDLE_TIMEOUT = 2 * 60;
+const SUMMARY_ICON_SIZE = 48;
+
+var NotificationsBox = GObject.registerClass({
+ Signals: { 'wake-up-screen': {} },
+}, class NotificationsBox extends St.BoxLayout {
+ _init() {
+ super._init({
+ vertical: true,
+ name: 'unlockDialogNotifications',
+ style_class: 'unlock-dialog-notifications-container',
+ });
+
+ this._scrollView = new St.ScrollView({ hscrollbar_policy: St.PolicyType.NEVER });
+ this._notificationBox = new St.BoxLayout({ vertical: true,
+ style_class: 'unlock-dialog-notifications-container' });
+ this._scrollView.add_actor(this._notificationBox);
+
+ this.add_child(this._scrollView);
+
+ this._sources = new Map();
+ Main.messageTray.getSources().forEach(source => {
+ this._sourceAdded(Main.messageTray, source, true);
+ });
+ this._updateVisibility();
+
+ this._sourceAddedId = Main.messageTray.connect('source-added', this._sourceAdded.bind(this));
+
+ this.connect('destroy', this._onDestroy.bind(this));
+ }
+
+ _onDestroy() {
+ if (this._sourceAddedId) {
+ Main.messageTray.disconnect(this._sourceAddedId);
+ this._sourceAddedId = 0;
+ }
+
+ let items = this._sources.entries();
+ for (let [source, obj] of items)
+ this._removeSource(source, obj);
+ }
+
+ _updateVisibility() {
+ this._notificationBox.visible =
+ this._notificationBox.get_children().some(a => a.visible);
+
+ this.visible = this._notificationBox.visible;
+ }
+
+ _makeNotificationCountText(count, isChat) {
+ if (isChat)
+ return ngettext("%d new message", "%d new messages", count).format(count);
+ else
+ return ngettext("%d new notification", "%d new notifications", count).format(count);
+ }
+
+ _makeNotificationSource(source, box) {
+ let sourceActor = new MessageTray.SourceActor(source, SUMMARY_ICON_SIZE);
+ box.add_child(sourceActor);
+
+ let textBox = new St.BoxLayout({ vertical: true });
+ box.add_child(textBox);
+
+ let title = new St.Label({ text: source.title,
+ style_class: 'unlock-dialog-notification-label' });
+ textBox.add(title);
+
+ let count = source.unseenCount;
+ let countLabel = new St.Label({ text: this._makeNotificationCountText(count, source.isChat),
+ style_class: 'unlock-dialog-notification-count-text' });
+ textBox.add(countLabel);
+
+ box.visible = count != 0;
+ return [title, countLabel];
+ }
+
+ _makeNotificationDetailedSource(source, box) {
+ let sourceActor = new MessageTray.SourceActor(source, SUMMARY_ICON_SIZE);
+ let sourceBin = new St.Bin({ child: sourceActor });
+ box.add(sourceBin);
+
+ let textBox = new St.BoxLayout({ vertical: true });
+ box.add_child(textBox);
+
+ let title = new St.Label({ text: source.title,
+ style_class: 'unlock-dialog-notification-label' });
+ textBox.add(title);
+
+ let visible = false;
+ for (let i = 0; i < source.notifications.length; i++) {
+ let n = source.notifications[i];
+
+ if (n.acknowledged)
+ continue;
+
+ let body = '';
+ if (n.bannerBodyText) {
+ body = n.bannerBodyMarkup
+ ? n.bannerBodyText
+ : GLib.markup_escape_text(n.bannerBodyText, -1);
+ }
+
+ let label = new St.Label({ style_class: 'unlock-dialog-notification-count-text' });
+ label.clutter_text.set_markup(`${n.title} ${body}`);
+ textBox.add(label);
+
+ visible = true;
+ }
+
+ box.visible = visible;
+ return [title, null];
+ }
+
+ _shouldShowDetails(source) {
+ return source.policy.detailsInLockScreen ||
+ source.narrowestPrivacyScope == MessageTray.PrivacyScope.SYSTEM;
+ }
+
+ _showSource(source, obj, box) {
+ if (obj.detailed)
+ [obj.titleLabel, obj.countLabel] = this._makeNotificationDetailedSource(source, box);
+ else
+ [obj.titleLabel, obj.countLabel] = this._makeNotificationSource(source, box);
+
+ box.visible = obj.visible && (source.unseenCount > 0);
+ }
+
+ _sourceAdded(tray, source, initial) {
+ let obj = {
+ visible: source.policy.showInLockScreen,
+ detailed: this._shouldShowDetails(source),
+ sourceDestroyId: 0,
+ sourceCountChangedId: 0,
+ sourceTitleChangedId: 0,
+ sourceUpdatedId: 0,
+ sourceBox: null,
+ titleLabel: null,
+ countLabel: null,
+ };
+
+ obj.sourceBox = new St.BoxLayout({ style_class: 'unlock-dialog-notification-source',
+ x_expand: true });
+ this._showSource(source, obj, obj.sourceBox);
+ this._notificationBox.add_child(obj.sourceBox);
+
+ obj.sourceCountChangedId = source.connect('notify::count', () => {
+ this._countChanged(source, obj);
+ });
+ obj.sourceTitleChangedId = source.connect('notify::title', () => {
+ this._titleChanged(source, obj);
+ });
+ obj.policyChangedId = source.policy.connect('notify', (policy, pspec) => {
+ if (pspec.name == 'show-in-lock-screen')
+ this._visibleChanged(source, obj);
+ else
+ this._detailedChanged(source, obj);
+ });
+ obj.sourceDestroyId = source.connect('destroy', () => {
+ this._onSourceDestroy(source, obj);
+ });
+
+ this._sources.set(source, obj);
+
+ if (!initial) {
+ // block scrollbars while animating, if they're not needed now
+ let boxHeight = this._notificationBox.height;
+ if (this._scrollView.height >= boxHeight)
+ this._scrollView.vscrollbar_policy = St.PolicyType.NEVER;
+
+ let widget = obj.sourceBox;
+ let [, natHeight] = widget.get_preferred_height(-1);
+ widget.height = 0;
+ widget.ease({
+ height: natHeight,
+ mode: Clutter.AnimationMode.EASE_OUT_QUAD,
+ duration: 250,
+ onComplete: () => {
+ this._scrollView.vscrollbar_policy = St.PolicyType.AUTOMATIC;
+ widget.set_height(-1);
+ },
+ });
+
+ this._updateVisibility();
+ if (obj.sourceBox.visible)
+ this.emit('wake-up-screen');
+ }
+ }
+
+ _titleChanged(source, obj) {
+ obj.titleLabel.text = source.title;
+ }
+
+ _countChanged(source, obj) {
+ // A change in the number of notifications may change whether we show
+ // details.
+ let newDetailed = this._shouldShowDetails(source);
+ let oldDetailed = obj.detailed;
+
+ obj.detailed = newDetailed;
+
+ if (obj.detailed || oldDetailed != newDetailed) {
+ // A new notification was pushed, or a previous notification was destroyed.
+ // Give up, and build the list again.
+
+ obj.sourceBox.destroy_all_children();
+ obj.titleLabel = obj.countLabel = null;
+ this._showSource(source, obj, obj.sourceBox);
+ } else {
+ let count = source.unseenCount;
+ obj.countLabel.text = this._makeNotificationCountText(count, source.isChat);
+ }
+
+ obj.sourceBox.visible = obj.visible && (source.unseenCount > 0);
+
+ this._updateVisibility();
+ if (obj.sourceBox.visible)
+ this.emit('wake-up-screen');
+ }
+
+ _visibleChanged(source, obj) {
+ if (obj.visible == source.policy.showInLockScreen)
+ return;
+
+ obj.visible = source.policy.showInLockScreen;
+ obj.sourceBox.visible = obj.visible && source.unseenCount > 0;
+
+ this._updateVisibility();
+ if (obj.sourceBox.visible)
+ this.emit('wake-up-screen');
+ }
+
+ _detailedChanged(source, obj) {
+ let newDetailed = this._shouldShowDetails(source);
+ if (obj.detailed == newDetailed)
+ return;
+
+ obj.detailed = newDetailed;
+
+ obj.sourceBox.destroy_all_children();
+ obj.titleLabel = obj.countLabel = null;
+ this._showSource(source, obj, obj.sourceBox);
+ }
+
+ _onSourceDestroy(source, obj) {
+ this._removeSource(source, obj);
+ this._updateVisibility();
+ }
+
+ _removeSource(source, obj) {
+ obj.sourceBox.destroy();
+ obj.sourceBox = obj.titleLabel = obj.countLabel = null;
+
+ source.disconnect(obj.sourceDestroyId);
+ source.disconnect(obj.sourceCountChangedId);
+ source.disconnect(obj.sourceTitleChangedId);
+ source.policy.disconnect(obj.policyChangedId);
+
+ this._sources.delete(source);
+ }
+});
+
var Clock = GObject.registerClass(
class UnlockDialogClock extends St.BoxLayout {
_init() {
@@ -113,6 +374,13 @@ var UnlockDialog = GObject.registerClass({
Main.ctrlAltTabManager.addGroup(this, _("Unlock Window"), 'dialog-password-symbolic');
+ // Notifications
+ this._notificationsBox = new NotificationsBox();
+ this._wakeUpScreenId = this._notificationsBox.connect('wake-up-screen', () => {
+ this.emit('wake-up-screen');
+ });
+ this._promptBox.add_child(this._notificationsBox);
+
this._idleMonitor = Meta.IdleMonitor.get_core();
this._idleWatchId = this._idleMonitor.add_idle_watch(IDLE_TIMEOUT * 1000, this._escape.bind(this));
@@ -161,6 +429,12 @@ var UnlockDialog = GObject.registerClass({
this._clock = null;
}
+ if (this._notificationsBox) {
+ this._notificationsBox.disconnect(this._wakeUpScreenId);
+ this._notificationsBox.destroy();
+ this._notificationsBox = null;
+ }
+
this.popModal();
if (this._idleWatchId) {