gnome-shell/js/ui/panelMenu.js
Ray Strode 388cfa3695 panelMenu: Separate from ui chrome layer
The chrome layer contains the user interface elements (e.g.,
the panel) that disappear when fullscreen windows get displayed.

Panel menus are currently put in the chrome layer, but don't need
to be, since they are only displayed when the user is interacting
with the shell and not a fullscreen application.

Putting panel menus in the chrome layer does mean they will get
stacked below shell interface elements that aren't in the chrome layer,
though.

This commit changes panel menus to be on the same layer as most other
shell elements, so they get properly stacked above those elements.

https://bugzilla.gnome.org/show_bug.cgi?id=657082
2011-08-28 12:17:13 -04:00

138 lines
4.7 KiB
JavaScript

/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
const Clutter = imports.gi.Clutter;
const Gtk = imports.gi.Gtk;
const Signals = imports.signals;
const St = imports.gi.St;
const Lang = imports.lang;
const PopupMenu = imports.ui.popupMenu;
const Main = imports.ui.main;
function Button(menuAlignment) {
this._init(menuAlignment);
}
Button.prototype = {
_init: function(menuAlignment) {
this.actor = new St.Bin({ style_class: 'panel-button',
reactive: true,
can_focus: true,
x_fill: true,
y_fill: false,
track_hover: true });
this.actor._delegate = this;
this.actor.connect('button-press-event', Lang.bind(this, this._onButtonPress));
this.actor.connect('key-press-event', Lang.bind(this, this._onSourceKeyPress));
this.menu = new PopupMenu.PopupMenu(this.actor, menuAlignment, St.Side.TOP);
this.menu.actor.add_style_class_name('panel-menu');
this.menu.connect('open-state-changed', Lang.bind(this, this._onOpenStateChanged));
this.menu.actor.connect('key-press-event', Lang.bind(this, this._onMenuKeyPress));
Main.uiGroup.add_actor(this.menu.actor);
this.menu.actor.hide();
},
_onButtonPress: function(actor, event) {
if (!this.menu.isOpen) {
// Setting the max-height won't do any good if the minimum height of the
// menu is higher then the screen; it's useful if part of the menu is
// scrollable so the minimum height is smaller than the natural height
let monitor = Main.layoutManager.primaryMonitor;
this.menu.actor.style = ('max-height: ' +
Math.round(monitor.height - Main.panel.actor.height) +
'px;');
}
this.menu.toggle();
},
_onSourceKeyPress: function(actor, event) {
let symbol = event.get_key_symbol();
if (symbol == Clutter.KEY_space || symbol == Clutter.KEY_Return) {
this.menu.toggle();
return true;
} else if (symbol == Clutter.KEY_Escape && this.menu.isOpen) {
this.menu.close();
return true;
} else if (symbol == Clutter.KEY_Down) {
if (!this.menu.isOpen)
this.menu.toggle();
this.menu.actor.navigate_focus(this.actor, Gtk.DirectionType.DOWN, false);
return true;
} else
return false;
},
_onMenuKeyPress: function(actor, event) {
let symbol = event.get_key_symbol();
if (symbol == Clutter.KEY_Left || symbol == Clutter.KEY_Right) {
let focusManager = St.FocusManager.get_for_stage(global.stage);
let group = focusManager.get_group(this.actor);
if (group) {
let direction = (symbol == Clutter.KEY_Left) ? Gtk.DirectionType.LEFT : Gtk.DirectionType.RIGHT;
group.navigate_focus(this.actor, direction, false);
return true;
}
}
return false;
},
_onOpenStateChanged: function(menu, open) {
if (open)
this.actor.add_style_pseudo_class('active');
else
this.actor.remove_style_pseudo_class('active');
},
destroy: function() {
this.actor._delegate = null;
this.menu.destroy();
this.actor.destroy();
this.emit('destroy');
}
};
Signals.addSignalMethods(Button.prototype);
/* SystemStatusButton:
*
* This class manages one System Status indicator (network, keyboard,
* volume, bluetooth...), which is just a PanelMenuButton with an
* icon and a tooltip
*/
function SystemStatusButton() {
this._init.apply(this, arguments);
}
SystemStatusButton.prototype = {
__proto__: Button.prototype,
_init: function(iconName,tooltipText) {
Button.prototype._init.call(this, 0.0);
this._iconActor = new St.Icon({ icon_name: iconName,
icon_type: St.IconType.SYMBOLIC,
style_class: 'system-status-icon' });
this.actor.set_child(this._iconActor);
this.setTooltip(tooltipText);
},
setIcon: function(iconName) {
this._iconActor.icon_name = iconName;
},
setGIcon: function(gicon) {
this._iconActor.gicon = gicon;
},
setTooltip: function(text) {
if (text != null) {
this.tooltip = text;
this.actor.has_tooltip = true;
this.actor.tooltip_text = text;
} else {
this.actor.has_tooltip = false;
this.tooltip = null;
}
}
};