messageTray: Add a new message tray indicator
This commit is contained in:
parent
f7223763d2
commit
26d2fb8a37
@ -1726,6 +1726,28 @@ StScrollBar StButton#vhandle:active {
|
|||||||
-shell-counter-overlap-y: 13px;
|
-shell-counter-overlap-y: 13px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.message-tray-indicator {
|
||||||
|
spacing: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-tray-indicator-count {
|
||||||
|
font-size: 1.2em;
|
||||||
|
font-weight: bold;
|
||||||
|
|
||||||
|
color: black;
|
||||||
|
background-color: rgba(255, 255, 255, 0.7);
|
||||||
|
border-radius: 1em;
|
||||||
|
padding: 1em;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-tray-indicator-glow {
|
||||||
|
height: 4px;
|
||||||
|
background-gradient-start: rgba(255, 255, 255, 0);
|
||||||
|
background-gradient-end: rgba(255, 255, 255, 1);
|
||||||
|
background-gradient-direction: vertical;
|
||||||
|
}
|
||||||
|
|
||||||
/* OSD */
|
/* OSD */
|
||||||
.osd-window {
|
.osd-window {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
169
js/ui/layout.js
169
js/ui/layout.js
@ -22,11 +22,6 @@ const KEYBOARD_ANIMATION_TIME = 0.15;
|
|||||||
const BACKGROUND_FADE_ANIMATION_TIME = 1.0;
|
const BACKGROUND_FADE_ANIMATION_TIME = 1.0;
|
||||||
const DEFAULT_BACKGROUND_COLOR = Clutter.Color.from_pixel(0x2e3436ff);
|
const DEFAULT_BACKGROUND_COLOR = Clutter.Color.from_pixel(0x2e3436ff);
|
||||||
|
|
||||||
// The message tray takes this much pressure
|
|
||||||
// in the pressure barrier at once to release it.
|
|
||||||
const MESSAGE_TRAY_PRESSURE_THRESHOLD = 250; // pixels
|
|
||||||
const MESSAGE_TRAY_PRESSURE_TIMEOUT = 1000; // ms
|
|
||||||
|
|
||||||
const HOT_CORNER_PRESSURE_THRESHOLD = 100; // pixels
|
const HOT_CORNER_PRESSURE_THRESHOLD = 100; // pixels
|
||||||
const HOT_CORNER_PRESSURE_TIMEOUT = 1000; // ms
|
const HOT_CORNER_PRESSURE_TIMEOUT = 1000; // ms
|
||||||
|
|
||||||
@ -150,7 +145,6 @@ const LayoutManager = new Lang.Class({
|
|||||||
|
|
||||||
this._keyboardIndex = -1;
|
this._keyboardIndex = -1;
|
||||||
this._rightPanelBarrier = null;
|
this._rightPanelBarrier = null;
|
||||||
this._trayBarrier = null;
|
|
||||||
|
|
||||||
this._inOverview = false;
|
this._inOverview = false;
|
||||||
this._updateRegionIdle = 0;
|
this._updateRegionIdle = 0;
|
||||||
@ -210,7 +204,6 @@ const LayoutManager = new Lang.Class({
|
|||||||
this.trayBox = new St.Widget({ name: 'trayBox',
|
this.trayBox = new St.Widget({ name: 'trayBox',
|
||||||
layout_manager: new Clutter.BinLayout() });
|
layout_manager: new Clutter.BinLayout() });
|
||||||
this.addChrome(this.trayBox);
|
this.addChrome(this.trayBox);
|
||||||
this._setupTrayPressure();
|
|
||||||
|
|
||||||
this.modalDialogGroup = new St.Widget({ name: 'modalDialogGroup',
|
this.modalDialogGroup = new St.Widget({ name: 'modalDialogGroup',
|
||||||
layout_manager: new Clutter.BinLayout() });
|
layout_manager: new Clutter.BinLayout() });
|
||||||
@ -449,50 +442,9 @@ const LayoutManager = new Lang.Class({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
_setupTrayPressure: function() {
|
|
||||||
this._trayPressure = new PressureBarrier(MESSAGE_TRAY_PRESSURE_THRESHOLD,
|
|
||||||
MESSAGE_TRAY_PRESSURE_TIMEOUT,
|
|
||||||
Shell.KeyBindingMode.NORMAL |
|
|
||||||
Shell.KeyBindingMode.OVERVIEW);
|
|
||||||
this._trayPressure.setEventFilter(this._trayBarrierEventFilter);
|
|
||||||
this._trayPressure.connect('trigger', function(barrier) {
|
|
||||||
if (Main.layoutManager.bottomMonitor.inFullscreen)
|
|
||||||
return;
|
|
||||||
|
|
||||||
Main.messageTray.openTray();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
_updateTrayBarrier: function() {
|
|
||||||
let monitor = this.bottomMonitor;
|
|
||||||
|
|
||||||
if (this._trayBarrier) {
|
|
||||||
this._trayPressure.removeBarrier(this._trayBarrier);
|
|
||||||
this._trayBarrier.destroy();
|
|
||||||
this._trayBarrier = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
this._trayBarrier = new Meta.Barrier({ display: global.display,
|
|
||||||
x1: monitor.x, x2: monitor.x + monitor.width,
|
|
||||||
y1: monitor.y + monitor.height, y2: monitor.y + monitor.height,
|
|
||||||
directions: Meta.BarrierDirection.NEGATIVE_Y });
|
|
||||||
this._trayPressure.addBarrier(this._trayBarrier);
|
|
||||||
},
|
|
||||||
|
|
||||||
_trayBarrierEventFilter: function(event) {
|
|
||||||
// Throw out all events where the pointer was grabbed by another
|
|
||||||
// client, as the client that grabbed the pointer expects to have
|
|
||||||
// complete control over it
|
|
||||||
if (event.grabbed && Main.modalCount == 0)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
|
|
||||||
_monitorsChanged: function() {
|
_monitorsChanged: function() {
|
||||||
this._updateMonitors();
|
this._updateMonitors();
|
||||||
this._updateBoxes();
|
this._updateBoxes();
|
||||||
this._updateTrayBarrier();
|
|
||||||
this._updateHotCorners();
|
this._updateHotCorners();
|
||||||
this._updateBackgrounds();
|
this._updateBackgrounds();
|
||||||
this._updateFullscreen();
|
this._updateFullscreen();
|
||||||
@ -1096,10 +1048,10 @@ const HotCorner = new Lang.Class({
|
|||||||
|
|
||||||
this._setupFallbackCornerIfNeeded(layoutManager);
|
this._setupFallbackCornerIfNeeded(layoutManager);
|
||||||
|
|
||||||
this._pressureBarrier = new PressureBarrier(HOT_CORNER_PRESSURE_THRESHOLD,
|
this._pressureBarrier = new TriggerablePressureBarrier(HOT_CORNER_PRESSURE_THRESHOLD,
|
||||||
HOT_CORNER_PRESSURE_TIMEOUT,
|
HOT_CORNER_PRESSURE_TIMEOUT,
|
||||||
Shell.KeyBindingMode.NORMAL |
|
Shell.KeyBindingMode.NORMAL |
|
||||||
Shell.KeyBindingMode.OVERVIEW);
|
Shell.KeyBindingMode.OVERVIEW);
|
||||||
this._pressureBarrier.connect('trigger', Lang.bind(this, this._toggleOverview));
|
this._pressureBarrier.connect('trigger', Lang.bind(this, this._toggleOverview));
|
||||||
|
|
||||||
// Cache the three ripples instead of dynamically creating and destroying them.
|
// Cache the three ripples instead of dynamically creating and destroying them.
|
||||||
@ -1277,14 +1229,12 @@ const PressureBarrier = new Lang.Class({
|
|||||||
Name: 'PressureBarrier',
|
Name: 'PressureBarrier',
|
||||||
|
|
||||||
_init: function(threshold, timeout, keybindingMode) {
|
_init: function(threshold, timeout, keybindingMode) {
|
||||||
this._threshold = threshold;
|
this.threshold = threshold;
|
||||||
this._timeout = timeout;
|
this.timeout = timeout;
|
||||||
this._keybindingMode = keybindingMode;
|
this._keybindingMode = keybindingMode;
|
||||||
this._barriers = [];
|
this._barriers = [];
|
||||||
this._eventFilter = null;
|
this._eventFilter = null;
|
||||||
|
this.reset();
|
||||||
this._isTriggered = false;
|
|
||||||
this._reset();
|
|
||||||
},
|
},
|
||||||
|
|
||||||
addBarrier: function(barrier) {
|
addBarrier: function(barrier) {
|
||||||
@ -1313,10 +1263,10 @@ const PressureBarrier = new Lang.Class({
|
|||||||
this._eventFilter = filter;
|
this._eventFilter = filter;
|
||||||
},
|
},
|
||||||
|
|
||||||
_reset: function() {
|
reset: function() {
|
||||||
this._barrierEvents = [];
|
this._barrierEvents = [];
|
||||||
this._currentPressure = 0;
|
|
||||||
this._lastTime = 0;
|
this._lastTime = 0;
|
||||||
|
this.currentPressure = 0;
|
||||||
},
|
},
|
||||||
|
|
||||||
_isHorizontal: function(barrier) {
|
_isHorizontal: function(barrier) {
|
||||||
@ -1337,12 +1287,21 @@ const PressureBarrier = new Lang.Class({
|
|||||||
return Math.abs(event.dy);
|
return Math.abs(event.dy);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
get currentPressure() {
|
||||||
|
return this._currentPressure;
|
||||||
|
},
|
||||||
|
|
||||||
|
set currentPressure(value) {
|
||||||
|
this._currentPressure = value;
|
||||||
|
this.emit('pressure-changed');
|
||||||
|
},
|
||||||
|
|
||||||
_trimBarrierEvents: function() {
|
_trimBarrierEvents: function() {
|
||||||
// Events are guaranteed to be sorted in time order from
|
// Events are guaranteed to be sorted in time order from
|
||||||
// oldest to newest, so just look for the first old event,
|
// oldest to newest, so just look for the first old event,
|
||||||
// and then chop events after that off.
|
// and then chop events after that off.
|
||||||
let i = 0;
|
let i = 0;
|
||||||
let threshold = this._lastTime - this._timeout;
|
let threshold = this._lastTime - this.timeout;
|
||||||
|
|
||||||
while (i < this._barrierEvents.length) {
|
while (i < this._barrierEvents.length) {
|
||||||
let [time, distance] = this._barrierEvents[i];
|
let [time, distance] = this._barrierEvents[i];
|
||||||
@ -1355,21 +1314,75 @@ const PressureBarrier = new Lang.Class({
|
|||||||
|
|
||||||
for (i = 0; i < firstNewEvent; i++) {
|
for (i = 0; i < firstNewEvent; i++) {
|
||||||
let [time, distance] = this._barrierEvents[i];
|
let [time, distance] = this._barrierEvents[i];
|
||||||
this._currentPressure -= distance;
|
this.currentPressure = distance;
|
||||||
}
|
}
|
||||||
|
|
||||||
this._barrierEvents = this._barrierEvents.slice(firstNewEvent);
|
this._barrierEvents = this._barrierEvents.slice(firstNewEvent);
|
||||||
},
|
},
|
||||||
|
|
||||||
_onBarrierLeft: function(barrier, event) {
|
_onBarrierLeft: function(barrier, event) {
|
||||||
this._reset();
|
this.reset();
|
||||||
|
},
|
||||||
|
|
||||||
|
_shouldUseEvent: function(barrier, event) {
|
||||||
|
if (this._eventFilter && this._eventFilter(event))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Throw out all events not in the proper keybinding mode
|
||||||
|
if (!(this._keybindingMode & Main.keybindingMode))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
let slide = this._getDistanceAlongBarrier(barrier, event);
|
||||||
|
let distance = this._getDistanceAcrossBarrier(barrier, event);
|
||||||
|
|
||||||
|
// Throw out events where the cursor is move more
|
||||||
|
// along the axis of the barrier than moving with
|
||||||
|
// the barrier.
|
||||||
|
if (slide > distance)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
|
||||||
|
_appendEvent: function(barrier, event) {
|
||||||
|
let distance = this._getDistanceAcrossBarrier(barrier, event);
|
||||||
|
|
||||||
|
this._lastTime = event.time;
|
||||||
|
|
||||||
|
this._trimBarrierEvents();
|
||||||
|
distance = Math.min(15, distance);
|
||||||
|
|
||||||
|
this._barrierEvents.push([event.time, distance]);
|
||||||
|
this.currentPressure += distance;
|
||||||
|
},
|
||||||
|
|
||||||
|
_onBarrierHit: function(barrier, event) {
|
||||||
|
if (!this._shouldUseEvent(barrier, event))
|
||||||
|
return;
|
||||||
|
|
||||||
|
this._appendEvent(barrier, event);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Signals.addSignalMethods(PressureBarrier.prototype);
|
||||||
|
|
||||||
|
const TriggerablePressureBarrier = new Lang.Class({
|
||||||
|
Name: 'TriggerablePressureBarrier',
|
||||||
|
Extends: PressureBarrier,
|
||||||
|
|
||||||
|
_init: function(threshold, timeout, keybindingMode) {
|
||||||
|
this.parent(threshold, timeout, keybindingMode);
|
||||||
this._isTriggered = false;
|
this._isTriggered = false;
|
||||||
},
|
},
|
||||||
|
|
||||||
_trigger: function() {
|
_trigger: function() {
|
||||||
this._isTriggered = true;
|
this._isTriggered = true;
|
||||||
this.emit('trigger');
|
this.emit('trigger');
|
||||||
this._reset();
|
this.reset();
|
||||||
|
},
|
||||||
|
|
||||||
|
_onBarrierLeft: function() {
|
||||||
|
this.parent();
|
||||||
|
this._isTriggered = false;
|
||||||
},
|
},
|
||||||
|
|
||||||
_onBarrierHit: function(barrier, event) {
|
_onBarrierHit: function(barrier, event) {
|
||||||
@ -1378,37 +1391,17 @@ const PressureBarrier = new Lang.Class({
|
|||||||
if (this._isTriggered)
|
if (this._isTriggered)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (this._eventFilter && this._eventFilter(event))
|
if (!this._shouldUseEvent(barrier, event))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Throw out all events not in the proper keybinding mode
|
if (distance >= this.threshold) {
|
||||||
if (!(this._keybindingMode & Main.keybindingMode))
|
|
||||||
return;
|
|
||||||
|
|
||||||
let slide = this._getDistanceAlongBarrier(barrier, event);
|
|
||||||
let distance = this._getDistanceAcrossBarrier(barrier, event);
|
|
||||||
|
|
||||||
if (distance >= this._threshold) {
|
|
||||||
this._trigger();
|
this._trigger();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Throw out events where the cursor is move more
|
this._appendEvent(barrier, event);
|
||||||
// along the axis of the barrier than moving with
|
|
||||||
// the barrier.
|
|
||||||
if (slide > distance)
|
|
||||||
return;
|
|
||||||
|
|
||||||
this._lastTime = event.time;
|
if (this.currentPressure >= this.threshold)
|
||||||
|
|
||||||
this._trimBarrierEvents();
|
|
||||||
distance = Math.min(15, distance);
|
|
||||||
|
|
||||||
this._barrierEvents.push([event.time, distance]);
|
|
||||||
this._currentPressure += distance;
|
|
||||||
|
|
||||||
if (this._currentPressure >= this._threshold)
|
|
||||||
this._trigger();
|
this._trigger();
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
Signals.addSignalMethods(PressureBarrier.prototype);
|
|
||||||
|
@ -19,6 +19,7 @@ const BoxPointer = imports.ui.boxpointer;
|
|||||||
const CtrlAltTab = imports.ui.ctrlAltTab;
|
const CtrlAltTab = imports.ui.ctrlAltTab;
|
||||||
const GnomeSession = imports.misc.gnomeSession;
|
const GnomeSession = imports.misc.gnomeSession;
|
||||||
const GrabHelper = imports.ui.grabHelper;
|
const GrabHelper = imports.ui.grabHelper;
|
||||||
|
const Layout = imports.ui.layout;
|
||||||
const Lightbox = imports.ui.lightbox;
|
const Lightbox = imports.ui.lightbox;
|
||||||
const Main = imports.ui.main;
|
const Main = imports.ui.main;
|
||||||
const PointerWatcher = imports.ui.pointerWatcher;
|
const PointerWatcher = imports.ui.pointerWatcher;
|
||||||
@ -48,6 +49,9 @@ const TRAY_DWELL_CHECK_INTERVAL = 100; // ms
|
|||||||
|
|
||||||
const IDLE_TIME = 1000;
|
const IDLE_TIME = 1000;
|
||||||
|
|
||||||
|
const MESSAGE_TRAY_PRESSURE_THRESHOLD = 250; // pixels
|
||||||
|
const MESSAGE_TRAY_PRESSURE_TIMEOUT = 1000; // ms
|
||||||
|
|
||||||
const State = {
|
const State = {
|
||||||
HIDDEN: 0,
|
HIDDEN: 0,
|
||||||
SHOWING: 1,
|
SHOWING: 1,
|
||||||
@ -1500,6 +1504,118 @@ const MessageTrayMenuButton = new Lang.Class({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const MessageTrayIndicator = new Lang.Class({
|
||||||
|
Name: 'MessageTrayIndicator',
|
||||||
|
|
||||||
|
_init: function(tray) {
|
||||||
|
this._tray = tray;
|
||||||
|
|
||||||
|
this.actor = new St.BoxLayout({ style_class: 'message-tray-indicator',
|
||||||
|
reactive: true,
|
||||||
|
track_hover: true,
|
||||||
|
vertical: true,
|
||||||
|
x_expand: true,
|
||||||
|
y_expand: true,
|
||||||
|
y_align: Clutter.ActorAlign.START });
|
||||||
|
this.actor.connect('notify::height', Lang.bind(this, function() {
|
||||||
|
this.actor.translation_y = -this.actor.height;
|
||||||
|
}));
|
||||||
|
this.actor.connect('button-press-event', Lang.bind(this, function() {
|
||||||
|
this._tray.openTray();
|
||||||
|
this._pressureBarrier.reset();
|
||||||
|
}));
|
||||||
|
|
||||||
|
this._count = new St.Label({ style_class: 'message-tray-indicator-count',
|
||||||
|
x_expand: true,
|
||||||
|
x_align: Clutter.ActorAlign.CENTER });
|
||||||
|
this.actor.add_child(this._count);
|
||||||
|
|
||||||
|
this._tray.connect('indicator-count-updated', Lang.bind(this, this._syncCount));
|
||||||
|
this._syncCount();
|
||||||
|
|
||||||
|
this._glow = new St.Widget({ style_class: 'message-tray-indicator-glow',
|
||||||
|
x_expand: true });
|
||||||
|
this.actor.add_child(this._glow);
|
||||||
|
|
||||||
|
this._pressureBarrier = new Layout.PressureBarrier(MESSAGE_TRAY_PRESSURE_THRESHOLD,
|
||||||
|
MESSAGE_TRAY_PRESSURE_TIMEOUT,
|
||||||
|
Shell.KeyBindingMode.NORMAL |
|
||||||
|
Shell.KeyBindingMode.OVERVIEW);
|
||||||
|
this._pressureBarrier.setEventFilter(this._barrierEventFilter);
|
||||||
|
Main.layoutManager.connect('monitors-changed', Lang.bind(this, this._updateBarrier));
|
||||||
|
this._updateBarrier();
|
||||||
|
|
||||||
|
this._pressureBarrier.connect('pressure-changed', Lang.bind(this, this._updatePressure));
|
||||||
|
this._pressureValue = 0;
|
||||||
|
this._syncGlow();
|
||||||
|
},
|
||||||
|
|
||||||
|
_updateBarrier: function() {
|
||||||
|
let monitor = Main.layoutManager.bottomMonitor;
|
||||||
|
|
||||||
|
if (this._barrier) {
|
||||||
|
this._pressureBarrier.removeBarrier(this._trayBarrier);
|
||||||
|
this._barrier.destroy();
|
||||||
|
this._barrier = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._barrier = new Meta.Barrier({ display: global.display,
|
||||||
|
x1: monitor.x, x2: monitor.x + monitor.width,
|
||||||
|
y1: monitor.y + monitor.height, y2: monitor.y + monitor.height,
|
||||||
|
directions: Meta.BarrierDirection.NEGATIVE_Y });
|
||||||
|
this._pressureBarrier.addBarrier(this._barrier);
|
||||||
|
},
|
||||||
|
|
||||||
|
_trayBarrierEventFilter: function(event) {
|
||||||
|
// Throw out all events where the pointer was grabbed by another
|
||||||
|
// client, as the client that grabbed the pointer expects to have
|
||||||
|
// complete control over it
|
||||||
|
if (event.grabbed && Main.modalCount == 0)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (this._tray.hasVisibleNotification())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
|
||||||
|
_syncCount: function() {
|
||||||
|
let count = this._tray.indicatorCount;
|
||||||
|
this._count.visible = (count > 0);
|
||||||
|
this._count.text = '' + count;
|
||||||
|
},
|
||||||
|
|
||||||
|
_syncGlow: function() {
|
||||||
|
let value = this._pressureValue;
|
||||||
|
let percent = value / this._pressureBarrier.threshold;
|
||||||
|
this.actor.opacity = Math.min(percent * 255, 255);
|
||||||
|
this.actor.visible = (value > 0);
|
||||||
|
},
|
||||||
|
|
||||||
|
get pressureValue() {
|
||||||
|
return this._pressureValue;
|
||||||
|
},
|
||||||
|
|
||||||
|
set pressureValue(value) {
|
||||||
|
this._pressureValue = value;
|
||||||
|
this._syncGlow();
|
||||||
|
},
|
||||||
|
|
||||||
|
_updatePressure: function() {
|
||||||
|
let value = this._pressureBarrier.currentPressure;
|
||||||
|
this.pressureValue = value;
|
||||||
|
if (value > 0) {
|
||||||
|
Tweener.removeTweens(this);
|
||||||
|
Tweener.addTween(this, { time: this._pressureBarrier.timeout / 1000,
|
||||||
|
pressureValue: 0 });
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
destroy: function() {
|
||||||
|
this.actor.destroy();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
const MessageTray = new Lang.Class({
|
const MessageTray = new Lang.Class({
|
||||||
Name: 'MessageTray',
|
Name: 'MessageTray',
|
||||||
|
|
||||||
@ -1683,6 +1799,11 @@ const MessageTray = new Lang.Class({
|
|||||||
|
|
||||||
this._messageTrayMenuButton = new MessageTrayMenuButton(this);
|
this._messageTrayMenuButton = new MessageTrayMenuButton(this);
|
||||||
this.actor.add_actor(this._messageTrayMenuButton.actor);
|
this.actor.add_actor(this._messageTrayMenuButton.actor);
|
||||||
|
|
||||||
|
this._indicator = new MessageTrayIndicator(this);
|
||||||
|
Main.layoutManager.trayBox.add_child(this._indicator.actor);
|
||||||
|
Main.layoutManager.trackChrome(this._indicator.actor);
|
||||||
|
this._grabHelper.addActor(this._indicator.actor);
|
||||||
},
|
},
|
||||||
|
|
||||||
close: function() {
|
close: function() {
|
||||||
@ -2149,6 +2270,10 @@ const MessageTray = new Lang.Class({
|
|||||||
this._updateState();
|
this._updateState();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
hasVisibleNotification: function() {
|
||||||
|
return this._notificationState != State.HIDDEN;
|
||||||
|
},
|
||||||
|
|
||||||
// All of the logic for what happens when occurs here; the various
|
// All of the logic for what happens when occurs here; the various
|
||||||
// event handlers merely update variables such as
|
// event handlers merely update variables such as
|
||||||
// 'this._pointerInNotification', 'this._traySummoned', etc, and
|
// 'this._pointerInNotification', 'this._traySummoned', etc, and
|
||||||
|
@ -263,8 +263,6 @@ const Overview = new Lang.Class({
|
|||||||
this._overview.add(this._controls.actor, { y_fill: true, expand: true });
|
this._overview.add(this._controls.actor, { y_fill: true, expand: true });
|
||||||
this._controls.actor.connect('scroll-event', Lang.bind(this, this._onScrollEvent));
|
this._controls.actor.connect('scroll-event', Lang.bind(this, this._onScrollEvent));
|
||||||
|
|
||||||
this._stack.add_actor(this._controls.indicatorActor);
|
|
||||||
|
|
||||||
// TODO - recalculate everything when desktop size changes
|
// TODO - recalculate everything when desktop size changes
|
||||||
this.dashIconSize = this._dash.iconSize;
|
this.dashIconSize = this._dash.iconSize;
|
||||||
this._dash.connect('icon-size-changed',
|
this._dash.connect('icon-size-changed',
|
||||||
|
@ -396,87 +396,6 @@ const DashSpacer = new Lang.Class({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const MessagesIndicator = new Lang.Class({
|
|
||||||
Name: 'MessagesIndicator',
|
|
||||||
|
|
||||||
_init: function(viewSelector) {
|
|
||||||
this._count = 0;
|
|
||||||
this._sources = [];
|
|
||||||
this._viewSelector = viewSelector;
|
|
||||||
|
|
||||||
this._container = new St.BoxLayout({ style_class: 'messages-indicator-contents',
|
|
||||||
reactive: true,
|
|
||||||
track_hover: true,
|
|
||||||
x_expand: true,
|
|
||||||
y_expand: true,
|
|
||||||
x_align: Clutter.ActorAlign.CENTER });
|
|
||||||
|
|
||||||
this._icon = new St.Icon({ icon_name: 'user-idle-symbolic',
|
|
||||||
icon_size: 16 });
|
|
||||||
this._container.add_actor(this._icon);
|
|
||||||
|
|
||||||
this._label = new St.Label();
|
|
||||||
this._container.add_actor(this._label);
|
|
||||||
|
|
||||||
this._highlight = new St.Widget({ style_class: 'messages-indicator-highlight',
|
|
||||||
x_expand: true,
|
|
||||||
y_expand: true,
|
|
||||||
y_align: Clutter.ActorAlign.END,
|
|
||||||
visible: false });
|
|
||||||
|
|
||||||
this._container.connect('notify::hover', Lang.bind(this,
|
|
||||||
function() {
|
|
||||||
this._highlight.visible = this._container.hover;
|
|
||||||
}));
|
|
||||||
|
|
||||||
let clickAction = new Clutter.ClickAction();
|
|
||||||
this._container.add_action(clickAction);
|
|
||||||
clickAction.connect('clicked', Lang.bind(this,
|
|
||||||
function() {
|
|
||||||
Main.messageTray.openTray();
|
|
||||||
}));
|
|
||||||
|
|
||||||
Main.messageTray.connect('showing', Lang.bind(this,
|
|
||||||
function() {
|
|
||||||
this._highlight.visible = false;
|
|
||||||
this._container.hover = false;
|
|
||||||
}));
|
|
||||||
|
|
||||||
let layout = new Clutter.BinLayout();
|
|
||||||
this.actor = new St.Widget({ layout_manager: layout,
|
|
||||||
style_class: 'messages-indicator',
|
|
||||||
y_expand: true,
|
|
||||||
y_align: Clutter.ActorAlign.END,
|
|
||||||
visible: false });
|
|
||||||
this.actor.add_actor(this._container);
|
|
||||||
this.actor.add_actor(this._highlight);
|
|
||||||
|
|
||||||
Main.messageTray.connect('indicator-count-updated', Lang.bind(this, this._sync));
|
|
||||||
this._sync();
|
|
||||||
|
|
||||||
this._viewSelector.connect('page-changed', Lang.bind(this, this._updateVisibility));
|
|
||||||
Main.overview.connect('showing', Lang.bind(this, this._updateVisibility));
|
|
||||||
},
|
|
||||||
|
|
||||||
_sync: function() {
|
|
||||||
let count = Main.messageTray.indicatorCount;
|
|
||||||
this._count = count;
|
|
||||||
this._label.text = ngettext("%d new message",
|
|
||||||
"%d new messages",
|
|
||||||
count).format(count);
|
|
||||||
|
|
||||||
this._icon.visible = Main.messageTray.hasChatSources;
|
|
||||||
this._updateVisibility();
|
|
||||||
},
|
|
||||||
|
|
||||||
_updateVisibility: function() {
|
|
||||||
let activePage = this._viewSelector.getActivePage();
|
|
||||||
let visible = ((this._count > 0) && (activePage == ViewSelector.ViewPage.WINDOWS));
|
|
||||||
|
|
||||||
this.actor.visible = visible;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const ControlsLayout = new Lang.Class({
|
const ControlsLayout = new Lang.Class({
|
||||||
Name: 'ControlsLayout',
|
Name: 'ControlsLayout',
|
||||||
Extends: Clutter.BinLayout,
|
Extends: Clutter.BinLayout,
|
||||||
@ -505,9 +424,6 @@ const ControlsManager = new Lang.Class({
|
|||||||
this.viewSelector.connect('page-changed', Lang.bind(this, this._setVisibility));
|
this.viewSelector.connect('page-changed', Lang.bind(this, this._setVisibility));
|
||||||
this.viewSelector.connect('page-empty', Lang.bind(this, this._onPageEmpty));
|
this.viewSelector.connect('page-empty', Lang.bind(this, this._onPageEmpty));
|
||||||
|
|
||||||
this._indicator = new MessagesIndicator(this.viewSelector);
|
|
||||||
this.indicatorActor = this._indicator.actor;
|
|
||||||
|
|
||||||
let layout = new ControlsLayout();
|
let layout = new ControlsLayout();
|
||||||
this.actor = new St.Widget({ layout_manager: layout,
|
this.actor = new St.Widget({ layout_manager: layout,
|
||||||
reactive: true,
|
reactive: true,
|
||||||
|
Loading…
Reference in New Issue
Block a user