[gnome-shell] [appDisplay] port from ShellMenu to PopupMenu
- From: Dan Winship <danw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-shell] [appDisplay] port from ShellMenu to PopupMenu
- Date: Thu, 10 Jun 2010 19:06:16 +0000 (UTC)
commit 748739ed9c365ac2d89b4d142c683caa12b85824
Author: Dan Winship <danw gnome org>
Date: Thu May 20 11:18:46 2010 -0400
[appDisplay] port from ShellMenu to PopupMenu
This fixes the style, and also makes it keyboard navigable
https://bugzilla.gnome.org/show_bug.cgi?id=619541
data/theme/gnome-shell.css | 23 +----
js/ui/appDisplay.js | 237 ++++++++++++++------------------------------
js/ui/workspace.js | 3 +
3 files changed, 78 insertions(+), 185 deletions(-)
---
diff --git a/data/theme/gnome-shell.css b/data/theme/gnome-shell.css
index 87c9250..8e0ef19 100644
--- a/data/theme/gnome-shell.css
+++ b/data/theme/gnome-shell.css
@@ -586,28 +586,7 @@ StTooltip {
}
.app-well-menu {
- border: 1px solid #5f5f5f;
- border-radius: 4px;
- padding: 4px;
- background-color: rgba(0,0,0,0.9);
- color: #ffffff;
- spacing: 4px;
-}
-
-.app-well-menu-arrow {
- border-color: #5f5f5f;
- color: rgba(0,0,0,0.9);
- width: 12px;
-}
-
-.app-well-menu-item:hover {
- background-color: #1e1e1e;
-}
-
-.app-well-menu-separator {
- padding-top: 1px;
- border-bottom: 1px solid #5f5f5f;
- height: 1px;
+ font-size: 12px
}
/* Places */
diff --git a/js/ui/appDisplay.js b/js/ui/appDisplay.js
index f43af8e..98dfb2f 100644
--- a/js/ui/appDisplay.js
+++ b/js/ui/appDisplay.js
@@ -18,6 +18,7 @@ const DND = imports.ui.dnd;
const GenericDisplay = imports.ui.genericDisplay;
const Main = imports.ui.main;
const Overview = imports.ui.overview;
+const PopupMenu = imports.ui.popupMenu;
const Search = imports.ui.search;
const Tweener = imports.ui.tweener;
const Workspace = imports.ui.workspace;
@@ -477,7 +478,9 @@ AppWellIcon.prototype = {
this.actor.set_child(this._icon.actor);
this.actor.connect('clicked', Lang.bind(this, this._onClicked));
+
this._menu = null;
+ this._menuManager = new PopupMenu.PopupMenuManager(this);
this._draggable = DND.makeDraggable(this.actor);
this._draggable.connect('drag-begin', Lang.bind(this,
@@ -527,7 +530,7 @@ AppWellIcon.prototype = {
this._removeMenuTimeout();
this._menuTimeoutId = Mainloop.timeout_add(MENU_POPUP_TIMEOUT,
Lang.bind(this, function() {
- this.popupMenu(button);
+ this.popupMenu();
}));
}
},
@@ -547,9 +550,7 @@ AppWellIcon.prototype = {
Main.overview.hide();
}
} else if (button == 3) {
- // Don't bind to the right click here; we want left click outside the
- // area to deactivate as well.
- this.popupMenu(0);
+ this.popupMenu();
}
return false;
},
@@ -558,7 +559,7 @@ AppWellIcon.prototype = {
return this.app.get_id();
},
- popupMenu: function(activatingButton) {
+ popupMenu: function() {
this._removeMenuTimeout();
this.actor.fake_release();
@@ -577,9 +578,12 @@ AppWellIcon.prototype = {
this._onMenuPoppedDown();
}
}));
+
+ this._menuManager.addMenu(this._menu, true);
}
- this._menu.popup(activatingButton);
+ this._menu.popup();
+ this._menuManager.grab();
return false;
},
@@ -646,6 +650,11 @@ AppWellIcon.prototype = {
Main.overview.hide();
},
+ // called by this._menuManager when it has the grab
+ menuEventFilter: function(event) {
+ return this._menu.menuEventFilter(event);
+ },
+
shellWorkspaceLaunch : function() {
this.app.open_new_window();
},
@@ -667,103 +676,34 @@ function AppIconMenu(source) {
}
AppIconMenu.prototype = {
+ __proto__: PopupMenu.PopupMenu.prototype,
+
_init: function(source) {
+ PopupMenu.PopupMenu.prototype._init.call(this, source.actor, St.Align.MIDDLE, St.Side.LEFT, 0);
+
this._source = source;
- this.actor = new Shell.GenericContainer({ reactive: true });
- this.actor.connect('get-preferred-width', Lang.bind(this, this._getPreferredWidth));
- this.actor.connect('get-preferred-height', Lang.bind(this, this._getPreferredHeight));
- this.actor.connect('allocate', Lang.bind(this, this._allocate));
-
- this._windowContainer = new Shell.Menu({ style_class: 'app-well-menu',
- vertical: true,
- width: Main.overview._dash.actor.width });
- this._windowContainer.connect('unselected', Lang.bind(this, this._onItemUnselected));
- this._windowContainer.connect('selected', Lang.bind(this, this._onItemSelected));
- this._windowContainer.connect('cancelled', Lang.bind(this, this._onWindowSelectionCancelled));
- this._windowContainer.connect('activate', Lang.bind(this, this._onItemActivate));
- this.actor.add_actor(this._windowContainer);
-
- // Stay popped up on release over application icon
- this._windowContainer.set_persistent_source(this._source.actor);
-
- // Intercept events while the menu has the pointer grab to do window-related effects
- this._windowContainer.connect('enter-event', Lang.bind(this, this._onMenuEnter));
- this._windowContainer.connect('leave-event', Lang.bind(this, this._onMenuLeave));
- this._windowContainer.connect('button-release-event', Lang.bind(this, this._onMenuButtonRelease));
-
- this._arrow = new St.DrawingArea({ style_class: 'app-well-menu-arrow' });
- this._arrow.connect('repaint', Lang.bind(this, function (area) {
- Shell.draw_box_pointer(area, Shell.PointerDirection.LEFT);
- }));
- this.actor.add_actor(this._arrow);
+ this.connect('active-changed', Lang.bind(this, this._onActiveChanged));
+ this.connect('activate', Lang.bind(this, this._onActivate));
+ this.connect('open-state-changed', Lang.bind(this, this._onOpenStateChanged));
+
+ this.actor.add_style_class_name('app-well-menu');
// Chain our visibility and lifecycle to that of the source
source.actor.connect('notify::mapped', Lang.bind(this, function () {
if (!source.actor.mapped)
- this._windowContainer.popdown();
+ this.close();
}));
source.actor.connect('destroy', Lang.bind(this, function () { this.actor.destroy(); }));
Main.uiGroup.add_actor(this.actor);
},
- _getPreferredWidth: function(actor, forHeight, alloc) {
- let [menuMin, menuNatural] = this._windowContainer.get_preferred_width(forHeight);
- let [arrowMin, arrowNatural] = this._arrow.get_preferred_width(forHeight);
- alloc.min_size = menuMin + arrowMin;
- alloc.natural_size = menuNatural + arrowNatural;
- },
-
- _getPreferredHeight: function(actor, forWidth, alloc) {
- let [min, natural] = this._windowContainer.get_preferred_height(forWidth);
- alloc.min_size = min;
- alloc.natural_size = natural;
- },
-
- _allocate: function(actor, box, flags) {
- let childBox = new Clutter.ActorBox();
- let themeNode = this._windowContainer.get_theme_node();
-
- let width = box.x2 - box.x1;
- let height = box.y2 - box.y1;
-
- let [arrowMinWidth, arrowWidth] = this._arrow.get_preferred_width(height);
-
- childBox.x1 = 0;
- childBox.x2 = arrowWidth;
- childBox.y1 = Math.floor((height / 2) - (arrowWidth / 2));
- childBox.y2 = childBox.y1 + arrowWidth;
- this._arrow.allocate(childBox, flags);
-
- // Ensure the arrow is above the border area
- let border = themeNode.get_border_width(St.Side.LEFT);
- childBox.x1 = arrowWidth - border;
- childBox.x2 = width;
- childBox.y1 = 0;
- childBox.y2 = height;
- this._windowContainer.allocate(childBox, flags);
- },
-
_redisplay: function() {
- this._windowContainer.remove_all();
+ this.removeAll();
let windows = this._source.app.get_windows();
- this._windowContainer.show();
-
- let iconsDiffer = false;
- let texCache = St.TextureCache.get_default();
- if (windows.length > 0) {
- let firstIcon = windows[0].mini_icon;
- for (let i = 1; i < windows.length; i++) {
- if (!texCache.pixbuf_equal(windows[i].mini_icon, firstIcon)) {
- iconsDiffer = true;
- break;
- }
- }
- }
-
// Display the app windows menu items and the separator between windows
// of the current desktop and other windows.
let activeWorkspace = global.screen.get_active_workspace();
@@ -774,8 +714,8 @@ AppIconMenu.prototype = {
this._appendSeparator();
separatorShown = true;
}
- let box = this._appendMenuItem(windows[i].title);
- box._window = windows[i];
+ let item = this._appendMenuItem(windows[i].title);
+ item._window = windows[i];
}
if (windows.length > 0)
@@ -794,45 +734,53 @@ AppIconMenu.prototype = {
},
_appendSeparator: function () {
- let bin = new St.Bin({ style_class: 'app-well-menu-separator' });
- this._windowContainer.add_actor(bin);
+ let separator = new PopupMenu.PopupSeparatorMenuItem();
+ this.addMenuItem(separator);
},
_appendMenuItem: function(labelText) {
- let box = new St.BoxLayout({ style_class: 'app-well-menu-item',
- reactive: true });
- let label = new St.Label({ text: labelText });
- box.add(label);
- this._windowContainer.add_actor(box);
- return box;
+ // FIXME: app-well-menu-item style
+ let item = new PopupMenu.PopupMenuItem(labelText);
+ this.addMenuItem(item);
+ return item;
},
popup: function(activatingButton) {
- let [stageX, stageY] = this._source.actor.get_transformed_position();
- let [stageWidth, stageHeight] = this._source.actor.get_transformed_size();
-
this._redisplay();
-
- this._windowContainer.popup(activatingButton, global.get_current_time());
-
- this.emit('popup', true);
-
- let x, y;
- x = Math.floor(stageX + stageWidth);
- y = Math.floor(stageY + (stageHeight / 2) - (this.actor.height / 2));
-
- this.actor.set_position(x, y);
- this.actor.show();
+ this.open();
},
- popdown: function() {
- this._windowContainer.popdown();
- this.emit('popup', false);
- this.actor.hide();
+ _onOpenStateChanged: function (menu, open) {
+ if (open) {
+ this.emit('popup', true);
+ } else {
+ this._updateHighlight(null);
+ this.emit('popup', false);
+ }
},
- selectWindow: function(metaWindow) {
- this._selectMenuItemForWindow(metaWindow);
+ // called by this._menuManager when it has the grab
+ menuEventFilter: function(event) {
+ let eventType = event.type();
+
+ // Check if the user is interacting with a window representation
+ // rather than interacting with the menu
+
+ if (eventType == Clutter.EventType.BUTTON_RELEASE) {
+ let metaWindow = this._findMetaWindowForActor(event.get_source());
+ if (metaWindow)
+ this.emit('activate-window', metaWindow);
+ } else if (eventType == Clutter.EventType.ENTER) {
+ let metaWindow = this._findMetaWindowForActor(event.get_source());
+ if (metaWindow)
+ this._selectMenuItemForWindow(metaWindow, true);
+ } else if (eventType == Clutter.EventType.LEAVE) {
+ let metaWindow = this._findMetaWindowForActor(event.get_source());
+ if (metaWindow)
+ this._selectMenuItemForWindow(metaWindow, false);
+ }
+
+ return false;
},
_findMetaWindowForActor: function (actor) {
@@ -843,64 +791,32 @@ AppIconMenu.prototype = {
return null;
},
- // This function is called while the menu has a pointer grab; what we want
- // to do is see if the mouse was released over a window representation
- _onMenuButtonRelease: function (actor, event) {
- let metaWindow = this._findMetaWindowForActor(event.get_source());
- if (metaWindow) {
- this.emit('activate-window', metaWindow);
- }
- },
-
_updateHighlight: function (item) {
- if (this._highlightedItem) {
- this._highlightedItem.remove_style_pseudo_class('hover');
+ if (this._highlightedItem)
this.emit('highlight-window', null);
- }
this._highlightedItem = item;
if (this._highlightedItem) {
- item.add_style_pseudo_class('hover');
let window = this._highlightedItem._window;
if (window)
this.emit('highlight-window', window);
}
},
- _selectMenuItemForWindow: function (metaWindow) {
- let children = this._windowContainer.get_children();
- for (let i = 0; i < children.length; i++) {
- let child = children[i];
- let menuMetaWindow = child._window;
+ _selectMenuItemForWindow: function (metaWindow, selected) {
+ let items = this.getMenuItems();
+ for (let i = 0; i < items.length; i++) {
+ let item = items[i];
+ let menuMetaWindow = item._window;
if (menuMetaWindow == metaWindow)
- this._updateHighlight(child);
- }
- },
-
- // Called while menu has a pointer grab
- _onMenuEnter: function (actor, event) {
- let metaWindow = this._findMetaWindowForActor(event.get_source());
- if (metaWindow) {
- this._selectMenuItemForWindow(metaWindow);
- }
- },
-
- // Called while menu has a pointer grab
- _onMenuLeave: function (actor, event) {
- let metaWindow = this._findMetaWindowForActor(event.get_source());
- if (metaWindow) {
- this._updateHighlight(null);
+ item.setActive(selected);
}
},
- _onItemUnselected: function (actor, child) {
- this._updateHighlight(null);
- },
-
- _onItemSelected: function (actor, child) {
+ _onActiveChanged: function (menu, child) {
this._updateHighlight(child);
},
- _onItemActivate: function (actor, child) {
+ _onActivate: function (actor, child) {
if (child._window) {
let metaWindow = child._window;
this.emit('activate-window', metaWindow);
@@ -915,12 +831,7 @@ AppIconMenu.prototype = {
else
favs.addFavorite(this._source.app.get_id());
}
- this.popdown();
- },
-
- _onWindowSelectionCancelled: function () {
- this.emit('highlight-window', null);
- this.popdown();
+ this.close();
}
};
Signals.addSignalMethods(AppIconMenu.prototype);
diff --git a/js/ui/workspace.js b/js/ui/workspace.js
index 1f14c1b..e917b8d 100644
--- a/js/ui/workspace.js
+++ b/js/ui/workspace.js
@@ -736,6 +736,9 @@ Workspace.prototype = {
* Draw the user's attention to the given window @metaWindow.
*/
setHighlightWindow: function (metaWindow) {
+ if (!this._lightbox)
+ return;
+
let actor;
if (metaWindow != null) {
let clone = this.lookupCloneForMetaWindow(metaWindow);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]