[gnome-shell] MessageTray: add right click menu for summary items
- From: Marina Zhurakhinskaya <marinaz src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-shell] MessageTray: add right click menu for summary items
- Date: Mon, 7 Mar 2011 16:15:05 +0000 (UTC)
commit 868bf5838d5a669efb8799827ab817435306e4cb
Author: Hellyna Ng <hellyna hellyna com>
Date: Sat Feb 12 03:43:01 2011 +0800
MessageTray: add right click menu for summary items
This provides straight forward controls for opening the corresponding
application or removing the summary item.
https://bugzilla.gnome.org/show_bug.cgi?id=617224
data/theme/gnome-shell.css | 10 ++-
js/ui/messageTray.js | 197 ++++++++++++++++++++++++--------------
js/ui/notificationDaemon.js | 2 +-
js/ui/popupMenu.js | 8 ++-
js/ui/telepathyClient.js | 2 +-
js/ui/windowAttentionHandler.js | 2 +-
6 files changed, 142 insertions(+), 79 deletions(-)
---
diff --git a/data/theme/gnome-shell.css b/data/theme/gnome-shell.css
index b317e6e..da69a3e 100644
--- a/data/theme/gnome-shell.css
+++ b/data/theme/gnome-shell.css
@@ -977,7 +977,7 @@ StTooltip StLabel {
padding-bottom: 8px;
}
-.summary-notification-boxpointer {
+.summary-boxpointer {
-arrow-border-radius: 9px;
-arrow-background-color: rgba(0,0,0,0.9);
-arrow-border-width: 2px;
@@ -986,12 +986,18 @@ StTooltip StLabel {
-arrow-rise: 15px;
}
-.summary-notification-boxpointer #notification {
+.summary-boxpointer #notification {
border-radius: 9px;
background: rgba(0,0,0,0) !important;
padding-bottom: 12px;
}
+.summary-boxpointer #summary-right-click-menu {
+ font-size: 14px;
+ padding-top: 12px;
+ padding-bottom: 12px;
+}
+
#notification-scrollview {
max-height: 10em;
}
diff --git a/js/ui/messageTray.js b/js/ui/messageTray.js
index d15bd62..29d882c 100644
--- a/js/ui/messageTray.js
+++ b/js/ui/messageTray.js
@@ -15,6 +15,7 @@ const St = imports.gi.St;
const BoxPointer = imports.ui.boxpointer;
const GnomeSession = imports.misc.gnomeSession;
const Main = imports.ui.main;
+const PopupMenu = imports.ui.popupMenu;
const Params = imports.misc.params;
const Tweener = imports.ui.tweener;
const Util = imports.misc.util;
@@ -853,7 +854,7 @@ Source.prototype = {
this.notification = notification;
- this._notificationClickedId = notification.connect('clicked', Lang.bind(this, this._notificationClicked));
+ this._notificationClickedId = notification.connect('clicked', Lang.bind(this, this.open));
this._notificationDestroyedId = notification.connect('destroy', Lang.bind(this,
function () {
if (this.notification == notification) {
@@ -881,7 +882,7 @@ Source.prototype = {
},
// Default implementation is to do nothing, but subclasses can override
- _notificationClicked: function(notification) {
+ open: function(notification) {
},
// Default implementation is to destroy this source, but subclasses can override
@@ -917,6 +918,27 @@ SummaryItem.prototype = {
this._sourceBox.add_actor(this._sourceIcon);
this._sourceBox.add_actor(this._sourceTitleBin, { expand: true });
this.actor.child = this._sourceBox;
+ this.rightClickMenu = new St.BoxLayout({ name: 'summary-right-click-menu',
+ vertical: true });
+
+ let item;
+
+ item = new PopupMenu.PopupMenuItem(_("Open"));
+ item.connect('activate', Lang.bind(this, function() {
+ source.open();
+ this.emit('right-click-menu-done-displaying');
+ }));
+ this.rightClickMenu.add(item.actor);
+
+ item = new PopupMenu.PopupMenuItem(_("Remove"));
+ item.connect('activate', Lang.bind(this, function() {
+ source.destroy();
+ this.emit('right-click-menu-done-displaying');
+ }));
+ this.rightClickMenu.add(item.actor);
+
+ let focusManager = St.FocusManager.get_for_stage(global.stage);
+ focusManager.add_group(this.rightClickMenu);
},
// getTitleNaturalWidth, getTitleWidth, and setTitleWidth include
@@ -943,6 +965,7 @@ SummaryItem.prototype = {
this._sourceTitle.clutter_text.ellipsize = mode;
}
};
+Signals.addSignalMethods(SummaryItem.prototype);
function MessageTray() {
this._init();
@@ -980,17 +1003,19 @@ MessageTray.prototype = {
this._summaryMotionId = 0;
- this._summaryNotificationBoxPointer = new BoxPointer.BoxPointer(St.Side.BOTTOM,
- { reactive: true,
- track_hover: true });
- this._summaryNotificationBoxPointer.actor.style_class = 'summary-notification-boxpointer';
- this.actor.add_actor(this._summaryNotificationBoxPointer.actor);
- this._summaryNotificationBoxPointer.actor.lower_bottom();
- this._summaryNotificationBoxPointer.actor.hide();
+ this._summaryBoxPointer = new BoxPointer.BoxPointer(St.Side.BOTTOM,
+ { reactive: true,
+ track_hover: true });
+ this._summaryBoxPointer.actor.style_class = 'summary-boxpointer';
+ this.actor.add_actor(this._summaryBoxPointer.actor);
+ this._summaryBoxPointer.actor.lower_bottom();
+ this._summaryBoxPointer.actor.hide();
this._summaryNotification = null;
this._summaryNotificationClickedId = 0;
+ this._summaryRightClickMenuClickedId = 0;
this._clickedSummaryItem = null;
+ this._clickedSummaryItemMouseButton = -1;
this._clickedSummaryItemAllocationChangedId = 0;
this._expandedSummaryItem = null;
this._summaryItemTitleWidth = 0;
@@ -1004,7 +1029,7 @@ MessageTray.prototype = {
this._focusGrabber = new FocusGrabber();
this._focusGrabber.connect('focus-grabbed', Lang.bind(this,
function() {
- if (this._summaryNotification)
+ if (this._summaryBoxPointer.bin.child)
this._lock();
}));
this._focusGrabber.connect('focus-ungrabbed', Lang.bind(this, this._unlock));
@@ -1027,7 +1052,7 @@ MessageTray.prototype = {
this._notificationState = State.HIDDEN;
this._notificationTimeoutId = 0;
this._notificationExpandedId = 0;
- this._summaryNotificationState = State.HIDDEN;
+ this._summaryBoxPointerState = State.HIDDEN;
this._summaryNotificationTimeoutId = 0;
this._summaryNotificationExpandedId = 0;
this._overviewVisible = Main.overview.visible;
@@ -1037,7 +1062,7 @@ MessageTray.prototype = {
Main.chrome.addActor(this.actor, { affectsStruts: false,
visibleInOverview: true });
Main.chrome.trackActor(this._notificationBin);
- Main.chrome.trackActor(this._summaryNotificationBoxPointer.actor);
+ Main.chrome.trackActor(this._summaryBoxPointer.actor);
global.gdk_screen.connect('monitors-changed', Lang.bind(this, this._setSizePosition));
@@ -1138,9 +1163,9 @@ MessageTray.prototype = {
this._onSummaryItemHoverChanged(summaryItem);
}));
- summaryItem.actor.connect('clicked', Lang.bind(this,
- function () {
- this._onSummaryItemClicked(summaryItem);
+ summaryItem.actor.connect('button-press-event', Lang.bind(this,
+ function (actor, event) {
+ this._onSummaryItemClicked(summaryItem, event);
}));
source.connect('destroy', Lang.bind(this, this._onSourceDestroy));
@@ -1354,11 +1379,16 @@ MessageTray.prototype = {
this._expandedSummaryItem.setEllipsization(Pango.EllipsizeMode.END);
},
- _onSummaryItemClicked: function(summaryItem) {
- if (!this._clickedSummaryItem || this._clickedSummaryItem != summaryItem)
+ _onSummaryItemClicked: function(summaryItem, event) {
+ let clickedButton = event.get_button();
+ if (!this._clickedSummaryItem ||
+ this._clickedSummaryItem != summaryItem ||
+ this._clickedSummaryItemMouseButton != clickedButton) {
this._clickedSummaryItem = summaryItem;
- else
+ this._clickedSummaryItemMouseButton = clickedButton;
+ } else {
this._unsetClickedSummaryItem();
+ }
this._updateState();
},
@@ -1385,7 +1415,7 @@ MessageTray.prototype = {
// leaving the tray. The tray is locked when the summary notification is visible anyway, but we
// should treat the mouse being over the summary notification as the tray being left for collapsing
// any expanded summary item other than the one related to the notification.
- if (this._summaryNotificationBoxPointer.bin.hover)
+ if (this._summaryBoxPointer.bin.hover)
return;
this._useLongerTrayLeftTimeout = false;
@@ -1543,19 +1573,23 @@ MessageTray.prototype = {
}
// Summary notification
- let haveSummaryNotification = this._clickedSummaryItem != null;
- let summaryNotificationIsMainNotification = (haveSummaryNotification &&
+ let haveClickedSummaryItem = this._clickedSummaryItem != null;
+ let summaryNotificationIsMainNotification = (haveClickedSummaryItem &&
this._clickedSummaryItem.source.notification == this._notification);
- let canShowSummaryNotification = this._summaryState == State.SHOWN;
- let wrongSummaryNotification = (haveSummaryNotification &&
+ let canShowSummaryBoxPointer = this._summaryState == State.SHOWN;
+ let wrongSummaryNotification = (this._clickedSummaryItemMouseButton == 1 &&
this._summaryNotification != this._clickedSummaryItem.source.notification);
-
- if (this._summaryNotificationState == State.HIDDEN) {
- if (haveSummaryNotification && !summaryNotificationIsMainNotification && canShowSummaryNotification)
- this._showSummaryNotification();
- } else if (this._summaryNotificationState == State.SHOWN) {
- if (!haveSummaryNotification || !canShowSummaryNotification || wrongSummaryNotification)
- this._hideSummaryNotification();
+ let wrongSummaryRightClickMenu = (this._clickedSummaryItemMouseButton == 3 &&
+ this._summaryBoxPointer.bin.child != this._clickedSummaryItem.rightClickMenu);
+ let wrongSummaryBoxPointer = (haveClickedSummaryItem &&
+ (wrongSummaryNotification || wrongSummaryRightClickMenu));
+
+ if (this._summaryBoxPointerState == State.HIDDEN) {
+ if (haveClickedSummaryItem && !summaryNotificationIsMainNotification && canShowSummaryBoxPointer)
+ this._showSummaryBoxPointer();
+ } else if (this._summaryBoxPointerState == State.SHOWN) {
+ if (!haveClickedSummaryItem || !canShowSummaryBoxPointer || wrongSummaryBoxPointer)
+ this._hideSummaryBoxPointer();
}
// Tray itself
@@ -1813,44 +1847,53 @@ MessageTray.prototype = {
this._expandedSummaryItemTitleWidth = this._summaryItemTitleWidth;
},
- _showSummaryNotification: function() {
- this._summaryNotification = this._clickedSummaryItem.source.notification;
- this._summaryNotificationClickedId = this._summaryNotification.connect('done-displaying',
- Lang.bind(this, this._escapeTray));
- let index = this._notificationQueue.indexOf(this._summaryNotification);
- if (index != -1)
- this._notificationQueue.splice(index, 1);
+ _showSummaryBoxPointer: function() {
+ if (this._clickedSummaryItemMouseButton == 1) {
+ let clickedSummaryItemNotification = this._clickedSummaryItem.source.notification;
+ let index = this._notificationQueue.indexOf(clickedSummaryItemNotification);
+ if (index != -1)
+ this._notificationQueue.splice(index, 1);
+
+ this._summaryNotification = clickedSummaryItemNotification;
+ this._summaryNotificationClickedId = this._summaryNotification.connect('done-displaying',
+ Lang.bind(this, this._escapeTray));
+ this._summaryBoxPointer.bin.child = this._summaryNotification.actor;
+ if (!this._summaryNotificationExpandedId)
+ this._summaryNotificationExpandedId = this._summaryNotification.connect('expanded',
+ Lang.bind(this, this._onSummaryBoxPointerExpanded));
+ this._summaryNotification.expand(false);
+ } else if (this._clickedSummaryItemMouseButton == 3) {
+ this._summaryRightClickMenuClickedId = this._clickedSummaryItem.connect('right-click-menu-done-displaying',
+ Lang.bind(this, this._escapeTray));
+ this._summaryBoxPointer.bin.child = this._clickedSummaryItem.rightClickMenu;
+ }
- this._summaryNotificationBoxPointer.bin.child = this._summaryNotification.actor;
- this._focusGrabber.grabFocus(this._summaryNotification.actor);
+ this._focusGrabber.grabFocus(this._summaryBoxPointer.bin.child);
- if (!this._summaryNotificationExpandedId)
- this._summaryNotificationExpandedId = this._summaryNotification.connect('expanded', Lang.bind(this, this._onSummaryNotificationExpanded));
- this._summaryNotification.expand(false);
this._clickedSummaryItemAllocationChangedId =
this._clickedSummaryItem.actor.connect('allocation-changed',
- Lang.bind(this, this._adjustNotificationBoxPointerPosition));
+ Lang.bind(this, this._adjustSummaryBoxPointerPosition));
// _clickedSummaryItem.actor can change absolute postiion without changing allocation
this._summaryMotionId = this._summary.connect('allocation-changed',
- Lang.bind(this, this._adjustNotificationBoxPointerPosition));
+ Lang.bind(this, this._adjustSummaryBoxPointerPosition));
- this._summaryNotificationBoxPointer.actor.opacity = 0;
- this._summaryNotificationBoxPointer.actor.show();
- this._adjustNotificationBoxPointerPosition();
+ this._summaryBoxPointer.actor.opacity = 0;
+ this._summaryBoxPointer.actor.show();
+ this._adjustSummaryBoxPointerPosition();
- this._summaryNotificationState = State.SHOWING;
- this._summaryNotificationBoxPointer.show(true, Lang.bind(this, function() {
- this._summaryNotificationState = State.SHOWN;
+ this._summaryBoxPointerState = State.SHOWING;
+ this._summaryBoxPointer.show(true, Lang.bind(this, function() {
+ this._summaryBoxPointerState = State.SHOWN;
}));
},
- _adjustNotificationBoxPointerPosition: function() {
+ _adjustSummaryBoxPointerPosition: function() {
// The position of the arrow origin should be the same as center of this._clickedSummaryItem.actor
if (!this._clickedSummaryItem)
return;
- this._summaryNotificationBoxPointer.setPosition(this._clickedSummaryItem.actor, 0, 0.5);
+ this._summaryBoxPointer.setPosition(this._clickedSummaryItem.actor, 0, 0.5);
},
_unsetClickedSummaryItem: function() {
@@ -1861,14 +1904,20 @@ MessageTray.prototype = {
this._summaryMotionId = 0;
}
+ if (this._summaryRightClickMenuClickedId) {
+ this._clickedSummaryItem.disconnect(this._summaryRightClickMenuClickedId);
+ this._summaryRightClickMenuClickedId = 0;
+ }
+
this._clickedSummaryItem = null;
+ this._clickedSummaryItemMouseButton = -1;
},
- _onSummaryNotificationExpanded: function() {
- this._adjustNotificationBoxPointerPosition();
+ _onSummaryBoxPointerExpanded: function() {
+ this._adjustSummaryBoxPointerPosition();
},
- _hideSummaryNotification: function() {
+ _hideSummaryBoxPointer: function() {
if (this._summaryNotificationExpandedId) {
this._summaryNotification.disconnect(this._summaryNotificationExpandedId);
this._summaryNotificationExpandedId = 0;
@@ -1878,23 +1927,25 @@ MessageTray.prototype = {
this._unsetClickedSummaryItem();
this._focusGrabber.ungrabFocus();
- this._summaryNotificationState = State.HIDING;
- this._summaryNotificationBoxPointer.hide(true, Lang.bind(this, this._hideSummaryNotificationCompleted));
- },
-
- _hideSummaryNotificationCompleted: function() {
- this._summaryNotificationState = State.HIDDEN;
- this._summaryNotificationBoxPointer.bin.child = null;
- this._summaryNotification.collapseCompleted();
- this._summaryNotification.disconnect(this._summaryNotificationClickedId);
- this._summaryNotificationClickedId = 0;
- let summaryNotification = this._summaryNotification;
- this._summaryNotification = null;
- if (summaryNotification.isTransient && !this._reNotifyWithSummaryNotificationAfterHide)
- summaryNotification.destroy(NotificationDestroyedReason.EXPIRED);
- if (this._reNotifyWithSummaryNotificationAfterHide) {
- this._onNotify(summaryNotification.source, summaryNotification);
- this._reNotifyWithSummaryNotificationAfterHide = false;
+ this._summaryBoxPointerState = State.HIDING;
+ this._summaryBoxPointer.hide(true, Lang.bind(this, this._hideSummaryBoxPointerCompleted));
+ },
+
+ _hideSummaryBoxPointerCompleted: function() {
+ this._summaryBoxPointerState = State.HIDDEN;
+ this._summaryBoxPointer.bin.child = null;
+ if (this._summaryNotification != null) {
+ this._summaryNotification.collapseCompleted();
+ this._summaryNotification.disconnect(this._summaryNotificationClickedId);
+ this._summaryNotificationClickedId = 0;
+ let summaryNotification = this._summaryNotification;
+ this._summaryNotification = null;
+ if (summaryNotification.isTransient && !this._reNotifyWithSummaryNotificationAfterHide)
+ summaryNotification.destroy(NotificationDestroyedReason.EXPIRED);
+ if (this._reNotifyWithSummaryNotificationAfterHide) {
+ this._onNotify(summaryNotification.source, summaryNotification);
+ this._reNotifyWithSummaryNotificationAfterHide = false;
+ }
}
if (this._clickedSummaryItem)
this._updateState();
@@ -1920,7 +1971,7 @@ SystemNotificationSource.prototype = {
icon_size: this.ICON_SIZE });
},
- _notificationClicked: function() {
+ open: function() {
this.destroy();
}
};
diff --git a/js/ui/notificationDaemon.js b/js/ui/notificationDaemon.js
index 2285d58..7953b85 100644
--- a/js/ui/notificationDaemon.js
+++ b/js/ui/notificationDaemon.js
@@ -473,7 +473,7 @@ Source.prototype = {
this._isTrayIcon = true;
},
- _notificationClicked: function(notification) {
+ open: function(notification) {
this.openApp();
},
diff --git a/js/ui/popupMenu.js b/js/ui/popupMenu.js
index 6e753fd..e16220c 100644
--- a/js/ui/popupMenu.js
+++ b/js/ui/popupMenu.js
@@ -54,8 +54,10 @@ PopupBaseMenuItem.prototype = {
}
if (params.reactive && params.hover)
this.actor.connect('notify::hover', Lang.bind(this, this._onHoverChanged));
- if (params.reactive)
+ if (params.reactive) {
this.actor.connect('key-focus-in', Lang.bind(this, this._onKeyFocusIn));
+ this.actor.connect('key-focus-out', Lang.bind(this, this._onKeyFocusOut));
+ }
},
_onStyleChanged: function (actor) {
@@ -81,6 +83,10 @@ PopupBaseMenuItem.prototype = {
this.setActive(true);
},
+ _onKeyFocusOut: function (actor) {
+ this.setActive(false);
+ },
+
_onHoverChanged: function (actor) {
this.setActive(actor.hover);
},
diff --git a/js/ui/telepathyClient.js b/js/ui/telepathyClient.js
index 5ddaaef..d835d3e 100644
--- a/js/ui/telepathyClient.js
+++ b/js/ui/telepathyClient.js
@@ -173,7 +173,7 @@ Source.prototype = {
}
},
- _notificationClicked: function(notification) {
+ open: function(notification) {
let props = {};
props[Tp.PROP_CHANNEL_CHANNEL_TYPE] = Tp.IFACE_CHANNEL_TYPE_TEXT;
[props[Tp.PROP_CHANNEL_TARGET_HANDLE], props[Tp.PROP_CHANNEL_TARGET_HANDLE_TYPE]] = this._channel.get_handle();
diff --git a/js/ui/windowAttentionHandler.js b/js/ui/windowAttentionHandler.js
index fd80cd9..560e915 100644
--- a/js/ui/windowAttentionHandler.js
+++ b/js/ui/windowAttentionHandler.js
@@ -101,7 +101,7 @@ Source.prototype = {
return this._app.create_icon_texture(this.ICON_SIZE);
},
- _notificationClicked : function(notification) {
+ open : function(notification) {
Main.activateWindow(this._window);
this.destroy();
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]