From 27bcce0888ffae12e7e679de1e78f4f9641efad1 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Mon, 10 May 2010 09:46:54 -0400 Subject: [PATCH] [panel] Port user status menu to panel menu https://bugzilla.gnome.org/show_bug.cgi?id=613804 --- data/theme/gnome-shell.css | 2 +- js/ui/panel.js | 26 ++----- js/ui/statusMenu.js | 143 +++++++++---------------------------- 3 files changed, 42 insertions(+), 129 deletions(-) diff --git a/data/theme/gnome-shell.css b/data/theme/gnome-shell.css index 83d846518..00c031fe7 100644 --- a/data/theme/gnome-shell.css +++ b/data/theme/gnome-shell.css @@ -186,7 +186,7 @@ StTooltip { border-radius-topright: 0px; } -#statusMenu { +#panelStatusMenu { spacing: 4px; } diff --git a/js/ui/panel.js b/js/ui/panel.js index e4e72e1c1..b046c221e 100644 --- a/js/ui/panel.js +++ b/js/ui/panel.js @@ -9,13 +9,13 @@ const Shell = imports.gi.Shell; const St = imports.gi.St; const Tweener = imports.ui.tweener; const Signals = imports.signals; +const DBus = imports.dbus; const Gettext = imports.gettext.domain('gnome-shell'); const _ = Gettext.gettext; const AppDisplay = imports.ui.appDisplay; const Calendar = imports.ui.calendar; const Main = imports.ui.main; -const StatusMenu = imports.ui.statusMenu; const BoxPointer = imports.ui.boxpointer; const PANEL_HEIGHT = 26; @@ -794,24 +794,12 @@ Panel.prototype = { })); this._traymanager.manage_stage(global.stage); - let statusmenu = this._statusmenu = new StatusMenu.StatusMenu(); - let statusbutton = new St.Clickable({ name: 'panelStatus', - style_class: 'panel-button', - reactive: true, - y_fill: true }); - statusbutton.set_child(statusmenu.actor); - statusbutton.connect('clicked', function (b, event) { - statusmenu.toggle(event); - // The statusmenu might not pop up if it couldn't get a pointer grab - if (statusmenu.isActive()) - statusbutton.active = true; - return true; - }); - this._rightBox.add(statusbutton); - // We get a deactivated event when the popup disappears - this._statusmenu.connect('deactivated', function (sm) { - statusbutton.active = false; - }); + // We need to do this here to avoid a circular import with + // prototype dependencies. + let StatusMenu = imports.ui.statusMenu; + this._statusmenu = new StatusMenu.StatusMenuButton(); + this._addMenu(this._statusmenu); + this._rightBox.add(this._statusmenu.actor); // TODO: decide what to do with the rest of the panel in the Overview mode (make it fade-out, become non-reactive, etc.) // We get into the Overview mode on button-press-event as opposed to button-release-event because eventually we'll probably diff --git a/js/ui/statusMenu.js b/js/ui/statusMenu.js index ed350c92a..70130d302 100644 --- a/js/ui/statusMenu.js +++ b/js/ui/statusMenu.js @@ -2,11 +2,9 @@ const Gdm = imports.gi.Gdm; const GLib = imports.gi.GLib; -const Gtk = imports.gi.Gtk; const Lang = imports.lang; const Shell = imports.gi.Shell; const St = imports.gi.St; -const Signals = imports.signals; const Gettext = imports.gettext.domain('gnome-shell'); const _ = Gettext.gettext; @@ -18,21 +16,26 @@ const Panel = imports.ui.panel; // Copyright (C) 2004-2005 James M. Cape . // Copyright (C) 2008,2009 Red Hat, Inc. -function StatusMenu() { +function StatusMenuButton() { this._init(); } -StatusMenu.prototype = { +StatusMenuButton.prototype = { + __proto__: Panel.PanelMenuButton.prototype, + _init: function() { + Panel.PanelMenuButton.prototype._init.call(this, St.Align.START); + let box = new St.BoxLayout({ name: 'panelStatusMenu' }); + this.actor.set_child(box); + this._gdm = Gdm.UserManager.ref_default(); this._user = this._gdm.get_user(GLib.get_user_name()); this._presence = new GnomeSession.Presence(); - this.actor = new St.BoxLayout({ name: 'statusMenu' }); this.actor.connect('destroy', Lang.bind(this, this._onDestroy)); this._iconBox = new St.Bin(); - this.actor.add(this._iconBox, { y_align: St.Align.MIDDLE, y_fill: false }); + box.add(this._iconBox, { y_align: St.Align.MIDDLE, y_fill: false }); let textureCache = St.TextureCache.get_default(); // FIXME: these icons are all wrong (likewise in createSubMenu) @@ -45,7 +48,7 @@ StatusMenu.prototype = { this._presence.getStatus(Lang.bind(this, this._updatePresenceIcon)); this._name = new St.Label({ text: this._user.get_real_name() }); - this.actor.add(this._name, { y_align: St.Align.MIDDLE, y_fill: false }); + box.add(this._name, { y_align: St.Align.MIDDLE, y_fill: false }); this._userNameChangedId = this._user.connect('notify::display-name', Lang.bind(this, this._updateUserName)); this._createSubMenu(); @@ -65,9 +68,9 @@ StatusMenu.prototype = { _updateSwitchUser: function() { let users = this._gdm.list_users(); if (users.length > 1) - this._loginScreenItem.show(); + this._loginScreenItem.actor.show(); else - this._loginScreenItem.hide(); + this._loginScreenItem.actor.hide(); }, _updatePresenceIcon: function(presence, status) { @@ -81,80 +84,51 @@ StatusMenu.prototype = { this._iconBox.child = this._idleIcon; }, - // The menu - - _createImageMenuItem: function(label, iconName, forceIcon) { - let image = new Gtk.Image(); - let item = new Gtk.ImageMenuItem({ label: label, - image: image, - always_show_image: forceIcon == true }); - item.connect('style-set', Lang.bind(this, - function() { - image.set_from_icon_name(iconName, Gtk.IconSize.MENU); - })); - - return item; - }, - _createSubMenu: function() { - this._menu = new Gtk.Menu(); - this._menu.connect('deactivate', Lang.bind(this, function() { this.emit('deactivated'); })); - let item; - item = this._createImageMenuItem(_("Available"), 'gtk-yes', true); + item = new Panel.PanelImageMenuItem(_("Available"), 'gtk-yes'); item.connect('activate', Lang.bind(this, this._setPresenceStatus, GnomeSession.PresenceStatus.AVAILABLE)); - this._menu.append(item); - item.show(); + this.menu.addMenuItem(item); - item = this._createImageMenuItem(_("Busy"), 'gtk-no', true); + item = new Panel.PanelImageMenuItem(_("Busy"), 'gtk-no'); item.connect('activate', Lang.bind(this, this._setPresenceStatus, GnomeSession.PresenceStatus.BUSY)); - this._menu.append(item); - item.show(); + this.menu.addMenuItem(item); - item = this._createImageMenuItem(_("Invisible"), 'gtk-close', true); + item = new Panel.PanelImageMenuItem(_("Invisible"), 'gtk-close'); item.connect('activate', Lang.bind(this, this._setPresenceStatus, GnomeSession.PresenceStatus.INVISIBLE)); - this._menu.append(item); - item.show(); + this.menu.addMenuItem(item); - item = new Gtk.SeparatorMenuItem(); - this._menu.append(item); - item.show(); + item = new Panel.PanelSeparatorMenuItem(); + this.menu.addMenuItem(item); - item = this._createImageMenuItem(_("Account Information..."), 'user-info'); + item = new Panel.PanelImageMenuItem(_("Account Information..."), 'user-info'); item.connect('activate', Lang.bind(this, this._onAccountInformationActivate)); - this._menu.append(item); - item.show(); + this.menu.addMenuItem(item); - item = this._createImageMenuItem(_("System Preferences..."), 'preferences-desktop'); + item = new Panel.PanelImageMenuItem(_("System Preferences..."), 'preferences-desktop'); item.connect('activate', Lang.bind(this, this._onPreferencesActivate)); - this._menu.append(item); - item.show(); + this.menu.addMenuItem(item); - item = new Gtk.SeparatorMenuItem(); - this._menu.append(item); - item.show(); + item = new Panel.PanelSeparatorMenuItem(); + this.menu.addMenuItem(item); - item = this._createImageMenuItem(_("Lock Screen"), 'system-lock-screen'); + item = new Panel.PanelImageMenuItem(_("Lock Screen"), 'system-lock-screen'); item.connect('activate', Lang.bind(this, this._onLockScreenActivate)); - this._menu.append(item); - item.show(); + this.menu.addMenuItem(item); - item = this._createImageMenuItem(_("Switch User"), 'system-users'); + item = new Panel.PanelImageMenuItem(_("Switch User"), 'system-users'); item.connect('activate', Lang.bind(this, this._onLoginScreenActivate)); - this._menu.append(item); - item.show(); + this.menu.addMenuItem(item); this._loginScreenItem = item; - item = this._createImageMenuItem(_("Log Out..."), 'system-log-out'); + item = new Panel.PanelImageMenuItem(_("Log Out..."), 'system-log-out'); item.connect('activate', Lang.bind(this, this._onQuitSessionActivate)); - this._menu.append(item); - item.show(); + this.menu.addMenuItem(item); - item = this._createImageMenuItem(_("Shut Down..."), 'system-shutdown'); + item = new Panel.PanelImageMenuItem(_("Shut Down..."), 'system-shutdown'); item.connect('activate', Lang.bind(this, this._onShutDownActivate)); - this._menu.append(item); - item.show(); + this.menu.addMenuItem(item); }, _setPresenceStatus: function(item, status) { @@ -192,54 +166,5 @@ StatusMenu.prototype = { // on failure let p = new Shell.Process({'args' : args}); p.run(); - }, - - // shell_status_menu_toggle: - // @event: event causing the toggle - // - // If the menu is not currently up, pops it up. Otherwise, hides it. - // Popping up may fail if another grab is already active; check with - // isActive(). - toggle: function(event) { - if (this._menu.visible) - this._menu.popdown(); - else { - // We don't want to overgrab a Mutter grab with the grab - // that GTK+ uses on menus. - if (global.display_is_grabbed()) - return; - - let [menuWidth, menuHeight] = this._menu.get_size_request (); - - let panel; - for (panel = this.actor; panel; panel = panel.get_parent()) { - if (panel._delegate instanceof Panel.Panel) - break; - } - - let [panelX, panelY] = panel.get_transformed_position(); - let [panelWidth, panelHeight] = panel.get_transformed_size(); - - let menuX; - if (St.Widget.get_default_direction() == St.TextDirection.RTL) { - menuX = panelX; - } else { - menuX = Math.round(panelX + panelWidth - menuWidth); - } - let menuY = Math.round(panelY + panelHeight); - - Shell.popup_menu(this._menu, event.get_button(), event.get_time(), - menuX, menuY); - } - }, - - // isActive: - // - // Gets whether the menu is currently popped up - // - // Return value: %true if the menu is currently popped up - isActive: function() { - return this._menu.visible; } }; -Signals.addSignalMethods(StatusMenu.prototype);