[gnome-shell/wip/gdm-shell: 2/6] wip: add very rough initial cut at gdm mode (needs-split)
- From: Ray Strode <halfline src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-shell/wip/gdm-shell: 2/6] wip: add very rough initial cut at gdm mode (needs-split)
- Date: Thu, 30 Jun 2011 02:05:41 +0000 (UTC)
commit 1b5000e0ec175b62fe2d7511f29a08dadce1156e
Author: Ray Strode <rstrode redhat com>
Date: Mon Jun 27 17:20:38 2011 -0400
wip: add very rough initial cut at gdm mode (needs-split)
This is just my in-progress code sketch pushed to a branch so
it's backed up.
data/Makefile.am | 1 +
data/theme/gnome-shell.css | 100 ++++++++
js/Makefile.am | 2 +
js/ui/calendar.js | 20 +-
js/ui/chrome.js | 10 +-
js/ui/dateMenu.js | 76 ++++---
js/ui/dialog.js | 228 ++++++++++++++++++
js/ui/loginDialog.js | 533 +++++++++++++++++++++++++++++++++++++++++
js/ui/main.js | 226 +++++++++++-------
js/ui/messageTray.js | 68 +++---
js/ui/notificationDaemon.js | 8 +-
js/ui/panel.js | 208 ++++++++++-------
js/ui/status/accessibility.js | 14 +-
js/ui/status/keyboard.js | 22 +-
js/ui/status/power.js | 13 +-
js/ui/status/volume.js | 14 +-
js/ui/windowManager.js | 32 ++--
17 files changed, 1276 insertions(+), 299 deletions(-)
---
diff --git a/data/Makefile.am b/data/Makefile.am
index 69fb40d..b8c08d6 100644
--- a/data/Makefile.am
+++ b/data/Makefile.am
@@ -38,6 +38,7 @@ dist_theme_DATA = \
theme/running-indicator.svg \
theme/scroll-hhandle.svg \
theme/scroll-vhandle.svg \
+ theme/selected-user.svg \
theme/source-button-border.svg \
theme/toggle-off-us.svg \
theme/toggle-off-intl.svg \
diff --git a/data/theme/gnome-shell.css b/data/theme/gnome-shell.css
index 7e7e786..c63c362 100644
--- a/data/theme/gnome-shell.css
+++ b/data/theme/gnome-shell.css
@@ -1661,3 +1661,103 @@ StTooltip StLabel {
.magnifier-zoom-region.full-screen {
border-width: 0px;
}
+/* Copyright 2011, Red Hat, Inc.
+ *
+ * Portions adapted from Mx's data/style/default.css
+ * Copyright 2009 Intel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU Lesser General Public License,
+ * version 2.1, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+.login-dialog-title {
+ font-size: 14pt;
+ font-weight: bold;
+ color: #666666;
+ padding-bottom: 2em;
+}
+
+.login-dialog {
+ border-radius: 16px;
+ min-height: 150px;
+ max-height: 700px;
+ min-width: 350px;
+}
+
+.login-dialog-user-list {
+ spacing: 12px;
+}
+
+.login-dialog-user-list:rtl {
+}
+
+.login-dialog-user-list-item {
+ color: #cccccc;
+}
+
+.login-dialog-user-list-item:ltr {
+ padding-right: 1em;
+}
+
+.login-dialog-user-list-item:rtl {
+ padding-left: 1em;
+}
+
+.login-dialog-user-list-item:hover {
+ color: white;
+ text-shadow: black 2px 2px 4px 4px;
+}
+
+.login-dialog-user-list-item:active {
+ color: white;
+ text-shadow: black 1px 1px 4px 4px;
+}
+
+.login-dialog-user-list-item-icon {
+ border: 2px solid #8b8b8b;
+ border-radius: 8px;
+ width: 64px;
+ height: 64px;
+}
+
+.login-dialog-user-list-item-name {
+ font-size: 20pt;
+ padding-left: 1em;
+}
+
+.login-dialog-not-listed-button {
+ padding-top: 2em;
+}
+.login-dialog-not-listed-label {
+ font-size: 14pt;
+ font-weight: bold;
+ color: #666666;
+}
+
+.login-dialog-prompt-layout {
+ padding-bottom: 64px;
+}
+.login-dialog-prompt-label {
+ color: white;
+ font-size: 20pt;
+}
+
+.login-dialog-prompt-entry {
+ padding: 4px;
+ border-radius: 4px;
+ border: 2px solid #5656cc;
+ color: black;
+ background-color: white;
+ caret-color: black;
+ caret-size: 1px;
+}
diff --git a/js/Makefile.am b/js/Makefile.am
index a085bfc..5cd0267 100644
--- a/js/Makefile.am
+++ b/js/Makefile.am
@@ -21,6 +21,7 @@ nobase_dist_js_DATA = \
ui/ctrlAltTab.js \
ui/dash.js \
ui/dateMenu.js \
+ ui/dialog.js \
ui/dnd.js \
ui/docDisplay.js \
ui/endSessionDialog.js \
@@ -29,6 +30,7 @@ nobase_dist_js_DATA = \
ui/iconGrid.js \
ui/lightbox.js \
ui/link.js \
+ ui/loginDialog.js \
ui/lookingGlass.js \
ui/magnifier.js \
ui/magnifierDBus.js \
diff --git a/js/ui/calendar.js b/js/ui/calendar.js
index 0f87305..0220f50 100644
--- a/js/ui/calendar.js
+++ b/js/ui/calendar.js
@@ -351,12 +351,14 @@ function Calendar(eventSource) {
Calendar.prototype = {
_init: function(eventSource) {
- this._eventSource = eventSource;
+ if (eventSource) {
+ this._eventSource = eventSource;
- this._eventSource.connect('changed', Lang.bind(this,
- function() {
- this._update(false);
- }));
+ this._eventSource.connect('changed', Lang.bind(this,
+ function() {
+ this._update(false);
+ }));
+ }
// FIXME: This is actually the fallback method for GTK+ for the week start;
// GTK+ by preference uses nl_langinfo (NL_TIME_FIRST_WEEKDAY). We probably
@@ -573,7 +575,7 @@ Calendar.prototype = {
this.setDate(newlySelectedDate, false);
}));
- let hasEvents = this._eventSource.hasEvents(iter);
+ let hasEvents = this._eventSource && this._eventSource.hasEvents(iter);
let styleClass = 'calendar-day-base calendar-day';
if (_isWorkDay(iter))
styleClass += ' calendar-work-day'
@@ -620,7 +622,8 @@ Calendar.prototype = {
}
// Signal to the event source that we are interested in events
// only from this date range
- this._eventSource.requestRange(beginDate, iter, forceReload);
+ if (this._eventSource)
+ this._eventSource.requestRange(beginDate, iter, forceReload);
}
};
@@ -667,6 +670,9 @@ EventsList.prototype = {
},
_addPeriod: function(header, begin, end, includeDayName, showNothingScheduled) {
+ if (!this._eventSource)
+ return;
+
let events = this._eventSource.getEvents(begin, end);
let clockFormat = this._desktopSettings.get_string(CLOCK_FORMAT_KEY);;
diff --git a/js/ui/chrome.js b/js/ui/chrome.js
index 474deb9..9b018c2 100644
--- a/js/ui/chrome.js
+++ b/js/ui/chrome.js
@@ -44,10 +44,12 @@ Chrome.prototype = {
global.screen.connect('notify::n-workspaces',
Lang.bind(this, this._queueUpdateRegions));
- Main.overview.connect('showing',
- Lang.bind(this, this._overviewShowing));
- Main.overview.connect('hidden',
- Lang.bind(this, this._overviewHidden));
+ if (Main.overview) {
+ Main.overview.connect('showing',
+ Lang.bind(this, this._overviewShowing));
+ Main.overview.connect('hidden',
+ Lang.bind(this, this._overviewHidden));
+ }
this._updateMonitors();
this._updateFullscreen();
diff --git a/js/ui/dateMenu.js b/js/ui/dateMenu.js
index a6a5196..708ed77 100644
--- a/js/ui/dateMenu.js
+++ b/js/ui/dateMenu.js
@@ -50,7 +50,9 @@ DateMenuButton.prototype = {
let hbox;
let vbox;
- this._eventSource = new Calendar.DBusEventSource();
+ if (global.session_type == Shell.SessionType.USER) {
+ this._eventSource = new Calendar.DBusEventSource();
+ }
let menuAlignment = 0.25;
if (St.Widget.get_default_direction() == St.TextDirection.RTL)
@@ -73,43 +75,51 @@ DateMenuButton.prototype = {
this._date.style_class = 'datemenu-date-label';
vbox.add(this._date);
- this._eventList = new Calendar.EventsList(this._eventSource);
+ if (this._eventSource) {
+ this._eventList = new Calendar.EventsList(this._eventSource);
+ }
// Calendar
this._calendar = new Calendar.Calendar(this._eventSource);
- this._calendar.connect('selected-date-changed',
- Lang.bind(this, function(calendar, date) {
- this._eventList.setDate(date);
- }));
+ if (this._eventList) {
+ this._calendar.connect('selected-date-changed',
+ Lang.bind(this, function(calendar, date) {
+ this._eventList.setDate(date);
+ }));
+ }
vbox.add(this._calendar.actor);
- item = new PopupMenu.PopupSeparatorMenuItem();
- item.setColumnWidths(1);
- vbox.add(item.actor, {y_align: St.Align.END, expand: true, y_fill: false});
- item = new PopupMenu.PopupMenuItem(_("Date and Time Settings"));
- item.connect('activate', Lang.bind(this, this._onPreferencesActivate));
- item.actor.can_focus = false;
- vbox.add(item.actor);
+ if (global.session_type == Shell.SessionType.USER) {
+ item = new PopupMenu.PopupSeparatorMenuItem();
+ item.setColumnWidths(1);
+ vbox.add(item.actor, {y_align: St.Align.END, expand: true, y_fill: false});
+ item = new PopupMenu.PopupMenuItem(_("Date and Time Settings"));
+ item.connect('activate', Lang.bind(this, this._onPreferencesActivate));
+ item.actor.can_focus = false;
+ vbox.add(item.actor);
- // Add vertical separator
+ // Add vertical separator
- item = new St.DrawingArea({ style_class: 'calendar-vertical-separator',
- pseudo_class: 'highlighted' });
- item.connect('repaint', Lang.bind(this, _onVertSepRepaint));
- hbox.add(item);
+ item = new St.DrawingArea({ style_class: 'calendar-vertical-separator',
+ pseudo_class: 'highlighted' });
+ item.connect('repaint', Lang.bind(this, _onVertSepRepaint));
+ hbox.add(item);
- // Fill up the second column
+ // Fill up the second column
- vbox = new St.BoxLayout({vertical: true});
- hbox.add(vbox, { expand: true });
+ vbox = new St.BoxLayout({vertical: true});
+ hbox.add(vbox, { expand: true });
- // Event list
- vbox.add(this._eventList.actor, { expand: true });
+ // Event list
+ if (this._eventList) {
+ vbox.add(this._eventList.actor, { expand: true });
+ }
- item = new PopupMenu.PopupMenuItem(_("Open Calendar"));
- item.connect('activate', Lang.bind(this, this._onOpenCalendarActivate));
- item.actor.can_focus = false;
- vbox.add(item.actor, {y_align: St.Align.END, expand: true, y_fill: false});
+ item = new PopupMenu.PopupMenuItem(_("Open Calendar"));
+ item.connect('activate', Lang.bind(this, this._onOpenCalendarActivate));
+ item.actor.can_focus = false;
+ vbox.add(item.actor, {y_align: St.Align.END, expand: true, y_fill: false});
+ }
// Whenever the menu is opened, select today
this.menu.connect('open-state-changed', Lang.bind(this, function(menu, isOpen) {
diff --git a/js/ui/dialog.js b/js/ui/dialog.js
new file mode 100644
index 0000000..c3df6f2
--- /dev/null
+++ b/js/ui/dialog.js
@@ -0,0 +1,228 @@
+/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
+
+const Clutter = imports.gi.Clutter;
+const Gdk = imports.gi.Gdk;
+const Gio = imports.gi.Gio;
+const GLib = imports.gi.GLib;
+const Lang = imports.lang;
+const Meta = imports.gi.Meta;
+const Pango = imports.gi.Pango;
+const St = imports.gi.St;
+const Shell = imports.gi.Shell;
+const Signals = imports.signals;
+const Gettext = imports.gettext.domain('gnome-shell');
+const _ = Gettext.gettext;
+
+const Params = imports.misc.params;
+
+const CtrlAltTab = imports.ui.ctrlAltTab;
+const Lightbox = imports.ui.lightbox;
+const Main = imports.ui.main;
+const Tweener = imports.ui.tweener;
+
+const OPEN_AND_CLOSE_TIME = 0.1;
+const FADE_OUT_DIALOG_TIME = 1.0;
+
+const State = {
+ OPENED: 0,
+ CLOSED: 1,
+ OPENING: 2,
+ CLOSING: 3,
+ FADED_OUT: 4
+};
+
+function Dialog() {
+ this._init();
+}
+
+Dialog.prototype = {
+ _init: function(params) {
+ params = Params.parse(params, { styleClass: null });
+
+ this.state = State.CLOSED;
+
+ this._group = new St.Group({ visible: false,
+ x: 0,
+ y: 0 });
+ Main.uiGroup.add_actor(this._group);
+
+ let constraint = new Clutter.BindConstraint({ source: global.stage,
+ coordinate: Clutter.BindCoordinate.POSITION | Clutter.BindCoordinate.SIZE });
+ this._group.add_constraint(constraint);
+
+ this._group.connect('destroy', Lang.bind(this, this._onGroupDestroy));
+
+ this._actionKeys = {};
+ this._group.connect('key-press-event', Lang.bind(this, this._onKeyPressEvent));
+
+ this._backgroundBin = new St.Bin();
+ this._group.add_actor(this._backgroundBin);
+
+ this._dialogLayout = new St.BoxLayout({ style_class: 'modal-dialog',
+ reactive: true,
+ can_focus: true,
+ vertical: true });
+ if (params.styleClass != null) {
+ this._dialogLayout.add_style_class_name(params.styleClass);
+ }
+
+ this._backgroundBin.add_actor(this._dialogLayout);
+
+ this.contentLayout = new St.BoxLayout({ vertical: true });
+ this._dialogLayout.add(this.contentLayout,
+ { x_fill: true,
+ y_fill: true,
+ x_align: St.Align.MIDDLE,
+ y_align: St.Align.START });
+
+ this._buttonLayout = new St.BoxLayout({ style_class: 'modal-dialog-button-box',
+ opacity: 220,
+ vertical: false });
+ this._dialogLayout.add(this._buttonLayout,
+ { expand: true,
+ x_align: St.Align.MIDDLE,
+ y_align: St.Align.END });
+
+ global.focus_manager.add_group(this._dialogLayout);
+ this._initialKeyFocus = this._dialogLayout;
+ this._savedKeyFocus = null;
+ },
+
+ setButtons: function(buttons) {
+ this._actionKeys = {};
+
+ let hadChildren = this._buttonLayout.get_children() > 0;
+
+ this._buttonLayout.destroy_children();
+
+ let i = 0;
+ for (let index in buttons) {
+ let buttonInfo = buttons[index];
+ let label = buttonInfo['label'];
+ let action = buttonInfo['action'];
+ let key = buttonInfo['key'];
+
+ let button = new St.Button({ style_class: 'modal-dialog-button',
+ reactive: true,
+ can_focus: true,
+ label: label });
+
+ let x_alignment;
+ if (buttons.length == 1)
+ x_alignment = St.Align.END;
+ else if (i == 0)
+ x_alignment = St.Align.START;
+ else if (i == buttons.length - 1)
+ x_alignment = St.Align.END;
+ else
+ x_alignment = St.Align.MIDDLE;
+
+ this._initialKeyFocus = button;
+ this._buttonLayout.add(button,
+ { expand: true,
+ x_fill: false,
+ y_fill: false,
+ x_align: x_alignment,
+ y_align: St.Align.MIDDLE });
+
+ if (!hadChildren) {
+ this._buttonLayout.opacity = 0;
+ Tweener.addTween(this._buttonLayout,
+ { opacity: 255,
+ time: 0.33,
+ transition: 'easeOutQuad',
+ onComplete: Lang.bind(this, function() {
+ })
+ });
+ }
+
+ button.connect('clicked', action);
+
+ if (key)
+ this._actionKeys[key] = action;
+ i++;
+ }
+ },
+
+ _onKeyPressEvent: function(object, keyPressEvent) {
+ let symbol = keyPressEvent.get_key_symbol();
+ let action = this._actionKeys[symbol];
+
+ if (action)
+ action();
+ },
+
+ _onGroupDestroy: function() {
+ this.emit('destroy');
+ },
+
+ _fadeOpen: function() {
+ let monitor = global.get_focus_monitor();
+
+ this._backgroundBin.set_position(monitor.x, monitor.y);
+ this._backgroundBin.set_size(monitor.width, monitor.height);
+
+ this.state = State.OPENING;
+
+ this._initialKeyFocus.grab_key_focus();
+
+ this._dialogLayout.opacity = 255;
+ this._group.opacity = 0;
+ this._group.show();
+ Tweener.addTween(this._group,
+ { opacity: 255,
+ time: OPEN_AND_CLOSE_TIME,
+ transition: 'easeOutQuad',
+ onComplete: Lang.bind(this,
+ function() {
+ this.state = State.OPENED;
+ this.emit('opened');
+ })
+ });
+ },
+
+ setInitialKeyFocus: function(actor) {
+ if (actor)
+ this._initialKeyFocus = actor;
+ },
+
+ open: function() {
+ if (this.state == State.OPENED || this.state == State.OPENING)
+ return true;
+
+ Main.ctrlAltTabManager.addGroup(this._group,
+ _("Login Window"),
+ 'dialog-password',
+ { sortGroup: CtrlAltTab.SortGroup.MIDDLE });
+
+ Main.pushModal(this._dialogLayout);
+
+ this._fadeOpen();
+ return true;
+ },
+
+ close: function() {
+ if (this.state == State.CLOSED || this.state == State.CLOSING)
+ return;
+
+ this.state = State.CLOSING;
+ this._savedKeyFocus = null;
+
+ Main.popModal(this._dialogLayout);
+
+ Main.ctrlAltTabManager.removeGroup(this._group);
+
+ Tweener.addTween(this._group,
+ { opacity: 0,
+ time: OPEN_AND_CLOSE_TIME,
+ transition: 'easeOutQuad',
+ onComplete: Lang.bind(this,
+ function() {
+ this.state = State.CLOSED;
+ this._group.hide();
+ })
+ });
+ },
+
+};
+Signals.addSignalMethods(Dialog.prototype);
diff --git a/js/ui/loginDialog.js b/js/ui/loginDialog.js
new file mode 100644
index 0000000..b521048
--- /dev/null
+++ b/js/ui/loginDialog.js
@@ -0,0 +1,533 @@
+/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*-
+ *
+ * Copyright 2010 Red Hat, Inc
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+const Lang = imports.lang;
+const Signals = imports.signals;
+
+const Gettext = imports.gettext.domain('gnome-shell');
+const _ = Gettext.gettext;
+
+const Clutter = imports.gi.Clutter;
+const CtrlAltTab = imports.ui.ctrlAltTab;
+const Gdm = imports.gi.Gdm;
+const Gio = imports.gi.Gio;
+const GLib = imports.gi.GLib;
+const Gtk = imports.gi.Gtk;
+const Mainloop = imports.mainloop;
+const Pango = imports.gi.Pango;
+const St = imports.gi.St;
+const Shell = imports.gi.Shell;
+const GdmGreeter = imports.gi.GdmGreeter;
+const AccountsService = imports.gi.AccountsService;
+
+const Dialog = imports.ui.dialog;
+const Lightbox = imports.ui.lightbox;
+const Main = imports.ui.main;
+const ModalDialog = imports.ui.modalDialog;
+const Tweener = imports.ui.tweener;
+
+const _DIALOG_ICON_SIZE = 64;
+
+let _loginDialog = null;
+
+function ListItem(user, reason) {
+ this._init(user, reason);
+}
+
+ListItem.prototype = {
+ _init: function(user) {
+ this.user = user;
+
+ let layout = new St.BoxLayout({ vertical: false });
+
+ this.actor = new St.Button({ style_class: 'login-dialog-user-list-item',
+ can_focus: true,
+ child: layout,
+ reactive: true,
+ x_align: St.Align.START,
+ x_fill: true });
+ this._userChangedId = this.user.connect('changed',
+ Lang.bind(this, this._onUserChanged));
+ this._iconBin = new St.Bin();
+ layout.add(this._iconBin);
+ let textLayout = new St.BoxLayout({ style_class: 'login-dialog-user-list-item-text-box',
+ vertical: true });
+ layout.add(textLayout,
+ { y_fill: false,
+ y_align: St.Align.MIDDLE,
+ expand: true });
+
+ this._nameLabel = new St.Label({ text: this.user.get_real_name(),
+ style_class: 'login-dialog-user-list-item-name' });
+ textLayout.add(this._nameLabel);
+
+ this._updateIcon();
+
+ this.actor.connect('clicked', Lang.bind(this, this._onClicked));
+ },
+
+ _onUserChanged: function() {
+ this._nameLabel.set_text(this.user.get_real_name());
+ this._updateIcon();
+ },
+
+ _setIconFromFile: function(iconFile, styleClass) {
+ if (styleClass)
+ this._iconBin.set_style_class_name(styleClass);
+ this._iconBin.set_style(null);
+
+ this._iconBin.child = null;
+ if (iconFile) {
+ this._iconBin.show();
+ this._iconBin.set_style('background-image: url("' + iconFile + '");');
+ } else {
+ this._iconBin.hide();
+ }
+ },
+
+ _setIconFromName: function(iconName, styleClass) {
+ if (styleClass)
+ this._iconBin.set_style_class_name(styleClass);
+ this._iconBin.set_style(null);
+
+ if (iconName != null) {
+ let gicon = new Gio.ThemedIcon({ name: iconName });
+ let icon = new St.Icon();
+ icon.set_gicon(gicon);
+
+ this._iconBin.child = icon;
+ this._iconBin.show();
+ } else {
+ this._iconBin.child = null;
+ this._iconBin.hide();
+ }
+ },
+
+ _updateIcon: function() {
+ let iconFileName = this.user.get_icon_file();
+ let gicon = null;
+
+ if (GLib.file_test(iconFileName, GLib.FileTest.EXISTS)) {
+ this._setIconFromFile(iconFileName, 'login-dialog-user-list-item-icon');
+ } else {
+ this._setIconFromName('avatar-default', 'login-dialog-user-list-item-icon');
+ }
+ },
+
+ _onClicked: function() {
+ this.emit('activate');
+ }
+
+};
+Signals.addSignalMethods(ListItem.prototype);
+
+function UserList() {
+ this._init.apply(this, arguments);
+}
+
+UserList.prototype = {
+ _init: function() {
+ this.actor = new St.ScrollView({ style_class: 'login-dialog-user-list'});
+ this.actor.set_policy(Gtk.PolicyType.NEVER,
+ Gtk.PolicyType.AUTOMATIC);
+
+ this._layout = new St.BoxLayout({ vertical: true,
+ style_class: 'login-dialog-user-list' });
+
+ this.actor.add_actor(this._layout,
+ { x_fill: true,
+ y_fill: true,
+ x_align: St.Align.START,
+ y_align: St.Align.MIDDLE });
+ this._items = {};
+ },
+
+ _hideItem: function(item) {
+ item.actor.hide();
+ },
+
+ _showItem: function(item) {
+ item.actor.show();
+ item._nameLabel.show();
+ },
+
+ _shrinkItem: function(item) {
+ item._nameLabel.hide();
+ },
+
+ _growItem: function(item) {
+ item._nameLabel.show();
+ },
+
+ _onItemActivated: function(activatedItem) {
+ this.actor.set_policy(Gtk.PolicyType.NEVER,
+ Gtk.PolicyType.NEVER);
+
+ for (userName in this._items) {
+ let item = this._items[userName];
+ if (item != activatedItem) {
+ this._hideItem(item);
+ } else {
+ this._shrinkItem(item);
+ }
+ }
+
+ this.emit('activate', activatedItem);
+ },
+
+ hideAllUsers: function() {
+ this.actor.set_policy(Gtk.PolicyType.NEVER,
+ Gtk.PolicyType.NEVER);
+
+ for (userName in this._items) {
+ let item = this._items[userName];
+ this._hideItem(item);
+ }
+ },
+
+ showAllUsers: function() {
+ for (userName in this._items) {
+ let item = this._items[userName];
+ this._showItem(item);
+ }
+
+ this.actor.set_policy(Gtk.PolicyType.NEVER,
+ Gtk.PolicyType.AUTOMATIC);
+ },
+
+ addUser: function(user) {
+ if (!user.is_loaded)
+ return null;
+
+ let userName = user.get_user_name();
+
+ if (!userName)
+ return null;
+
+ this.removeUser(user);
+
+ let item = new ListItem(user);
+ this._layout.add(item.actor, { x_fill: true });
+
+ this._items[userName] = item;
+
+ item.connect('activate',
+ Lang.bind(this, this._onItemActivated));
+
+ return item;
+ },
+
+ removeUser: function(user) {
+ if (!user.is_loaded)
+ return;
+
+ let userName = user.get_user_name();
+
+ if (!userName)
+ return;
+
+ let item = this._items[userName];
+
+ if (!item)
+ return;
+
+ item.actor.destroy();
+ delete this._items[userName];
+ }
+};
+Signals.addSignalMethods(UserList.prototype);
+
+function LoginDialog() {
+ if (_loginDialog == null) {
+ this._init();
+ _loginDialog = this;
+ }
+
+ return _loginDialog;
+}
+
+LoginDialog.prototype = {
+ __proto__: Dialog.Dialog.prototype,
+
+ _init: function() {
+ Dialog.Dialog.prototype._init.call(this, { styleClass: 'login-dialog' });
+
+ this.connect('destroy',
+ Lang.bind(this, this._onDestroy));
+ this.connect('opened',
+ Lang.bind(this, this._onOpened));
+
+ this._userManager = AccountsService.UserManager.get_default()
+ this._greeterClient = new GdmGreeter.Client();
+
+ this._greeterClient.open_connection();
+
+ this._greeterClient.call_start_conversation('gdm-password');
+
+ this._greeterClient.connect('ready',
+ Lang.bind(this, this._onReady));
+ this._greeterClient.connect('reset',
+ Lang.bind(this, this._onReset));
+ this._greeterClient.connect('info',
+ Lang.bind(this, this._onInfo));
+ this._greeterClient.connect('problem',
+ Lang.bind(this, this._onProblem));
+ this._greeterClient.connect('info-query',
+ Lang.bind(this, this._onInfoQuery));
+ this._greeterClient.connect('secret-info-query',
+ Lang.bind(this, this._onSecretInfoQuery));
+ this._greeterClient.connect('session-opened',
+ Lang.bind(this, this._onSessionOpened));
+ this._greeterClient.connect('timed-login-requested',
+ Lang.bind(this, this._onTimedLoginRequested));
+ this._greeterClient.connect('authentication-failed',
+ Lang.bind(this, this._onAuthenticationFailed));
+ this._greeterClient.connect('conversation-stopped',
+ Lang.bind(this, this._onConversationStopped));
+
+ this._titleLabel = new St.Label({ style_class: 'login-dialog-title',
+ text: _("Sign In") });
+
+ this.contentLayout.add(this._titleLabel,
+ { y_fill: false,
+ y_align: St.Align.START });
+
+ let mainContentLayout = new St.BoxLayout({ vertical: false });
+ this.contentLayout.add(mainContentLayout,
+ { x_fill: true,
+ y_fill: false });
+
+ this._userList = new UserList();
+ mainContentLayout.add(this._userList.actor,
+ { x_fill: true,
+ y_fill: true });
+
+ this._promptLayout = new St.BoxLayout({ style_class: 'login-dialog-prompt-layout',
+ vertical: true });
+ mainContentLayout.add(this._promptLayout,
+ { expand: true,
+ x_fill: true,
+ y_fill: true,
+ x_align: St.Align.START });
+ this._promptLabel = new St.Label({ style_class: 'login-dialog-prompt-label' });
+ this._promptLayout.add(this._promptLabel,
+ { expand: true,
+ x_fill: true,
+ y_fill: true,
+ x_align: St.Align.START });
+ this._promptEntry = new St.Entry({ style_class: 'login-dialog-prompt-entry' });
+ this._promptLayout.add(this._promptEntry,
+ { expand: true,
+ x_fill: true,
+ y_fill: false,
+ x_align: St.Align.START});
+ this._promptLayout.hide();
+
+ let notListedLabel = new St.Label({ text: _("Not listed?"),
+ style_class: 'login-dialog-not-listed-label' });
+ this._notListedButton = new St.Button({ style_class: 'login-dialog-not-listed-button',
+ can_focus: true,
+ child: notListedLabel,
+ reactive: true,
+ x_align: St.Align.START,
+ x_fill: true });
+
+ this._notListedButton.connect('clicked', Lang.bind(this, this._onNotListedClicked));
+
+ this.contentLayout.add(this._notListedButton,
+ { expand: false,
+ x_align: St.Align.START,
+ x_fill: true });
+
+ if (!this._userManager.is_loaded) {
+ this._userManagerLoadedId = this._userManager.connect('notify::is-loaded',
+ Lang.bind(this, function() {
+ if (this._userManager.is_loaded) {
+ this._loadUserList();
+ this._userManager.disconnect(this._userManagerLoadedId);
+ this._userManagerLoadedId = 0;
+ }
+ }));
+ } else {
+ this._loadUserList();
+ }
+
+ this._userList.connect('activate',
+ Lang.bind(this, function(userList, user) {
+ this._onUserListActivated(user);
+ }));
+
+ },
+
+ _onReady: function(client, serviceName) {
+ },
+
+ _onReset: function(client, serviceName) {
+ this._greeterClient.call_start_conversation('gdm-password');
+
+ this._promptEntry.set_text('');
+
+ if (this._promptEntryActivateCallbackId) {
+ this._promptEntry.clutter_text.disconnect(this._promptEntryActivateCallbackId);
+ this._promptEntryActivateCallbackId = null;
+ }
+
+ this.setButtons([]);
+
+ this._promptLabel.hide();
+ this._promptLayout.hide();
+
+ this._userList.showAllUsers();
+ this._userList.actor.grab_key_focus();
+
+ this._notListedButton.show();
+ this._titleLabel.show();
+ },
+
+ _onInfo: function(client, serviceName, info) {
+ Main.notifyError(info);
+ },
+
+ _onProblem: function(client, serviceName, problem) {
+ Main.notifyError(problem);
+ },
+
+ _onCancel: function(client) {
+ this._greeterClient.call_cancel();
+ },
+
+ _onSignIn: function(serviceName) {
+ let _text = this._promptEntry.get_text();
+ this._promptEntry.set_text('');
+
+ this._greeterClient.call_answer_query(serviceName, _text);
+ },
+
+ _showPrompt: function(callback) {
+ let buttons = [{ action: Lang.bind(this, this._onCancel),
+ label: _("Cancel"),
+ key: Clutter.Escape },
+ { action: callback,
+ label: _("Sign In") }];
+
+ if (!this._promptLayout.visible) {
+ this._promptLayout.show();
+ this._promptLabel.show();
+ this._promptEntry.show();
+ this._promptEntry.grab_key_focus();
+ }
+
+ this._promptEntryActivateCallbackId = this._promptEntry.clutter_text.connect('activate',
+ Lang.bind(this, function() {
+ callback();
+ this._promptEntry.clutter_text.disconnect(this._promptEntryActivateCallbackId);
+ this._promptEntryActivateCallbackId = null;
+ }));
+
+ this.setButtons(buttons);
+ },
+
+ _onInfoQuery: function(client, serviceName, question) {
+ this._promptEntry.set_text('');
+ this._promptEntry.clutter_text.set_password_char('');
+ this._promptLabel.set_text(question);
+ this._showPrompt(Lang.bind(this, function() {
+ this._onSignIn(serviceName);
+ }));
+
+ },
+
+ _onSecretInfoQuery: function(client, serviceName, secretQuestion) {
+ this._promptEntry.set_text('');
+ this._promptEntry.clutter_text.set_password_char('\u25cf');
+ this._promptLabel.set_text(secretQuestion);
+
+ this._showPrompt(Lang.bind(this, function() {
+ this._onSignIn(serviceName);
+ }));
+ },
+
+ _onSessionOpened: function(client, serviceName) {
+ this._greeterClient.call_start_session_when_ready(serviceName, true);
+ },
+
+ _onTimedLoginRequested: function(client, serviceName, seconds) {
+ },
+
+ _onAuthenticationFailed: function(client) {
+ this._greeterClient.call_cancel();
+ },
+
+ _onConversationStopped: function(client, serviceName) {
+ this._greeterClient.call_cancel();
+ },
+
+ _onNotListedClicked: function(user) {
+ this._titleLabel.hide();
+ this._notListedButton.hide();
+ this._userList.hideAllUsers();
+ this._greeterClient.call_begin_verification('gdm-password');
+ },
+
+ _onUserListActivated: function(item) {
+ this._titleLabel.hide();
+ this._notListedButton.hide();
+ this._greeterClient.call_begin_verification_for_user('gdm-password',
+ item.user.get_user_name());
+ },
+
+ _onDestroy: function() {
+ if (this._userManagerLoadedId) {
+ this._userManager.disconnect(this._userManagerLoadedId);
+ this._userManagerLoadedId = 0;
+ }
+ },
+
+ _loadUserList: function() {
+ let users = this._userManager.list_users();
+ let item = null;
+
+ for (let i = 0; i < users.length; i++) {
+ if (!item)
+ item = this._userList.addUser(users[i]);
+ else
+ this._userList.addUser(users[i]);
+ }
+
+ this._userManager.connect('user-added',
+ Lang.bind(this, function(userManager, user) {
+ if (!user.is_system_account())
+ this._userList.addUser(user);
+ }));
+
+ this._userManager.connect('user-removed',
+ Lang.bind(this, function(userManager, user) {
+ this._userList.removeUser(user);
+ }));
+
+ Mainloop.idle_add(Lang.bind(this, function() {
+ this.emit('loaded');
+ }));
+ },
+
+ _onOpened: function() {
+ this._userList.actor.grab_key_focus();
+ },
+};
diff --git a/js/ui/main.js b/js/ui/main.js
index 43fcfa5..025d0e7 100644
--- a/js/ui/main.js
+++ b/js/ui/main.js
@@ -1,8 +1,11 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
+imports.gi.versions.Clutter = '1.0';
+
const Clutter = imports.gi.Clutter;
const DBus = imports.dbus;
const Gdk = imports.gi.Gdk;
+const GdmGreeter = imports.gi.GdmGreeter;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const GConf = imports.gi.GConf;
@@ -18,6 +21,7 @@ const EndSessionDialog = imports.ui.endSessionDialog;
const PolkitAuthenticationAgent = imports.ui.polkitAuthenticationAgent;
const Environment = imports.ui.environment;
const ExtensionSystem = imports.ui.extensionSystem;
+const LoginDialog = imports.ui.loginDialog;
const MessageTray = imports.ui.messageTray;
const Overview = imports.ui.overview;
const Panel = imports.ui.panel;
@@ -39,10 +43,12 @@ const DEFAULT_BACKGROUND_COLOR = new Clutter.Color();
DEFAULT_BACKGROUND_COLOR.from_pixel(0x2266bbff);
let chrome = null;
+let greeterClient = null;
let panel = null;
let hotCorners = [];
let placesManager = null;
let overview = null;
+let loginDialog = null;
let runDialog = null;
let lookingGlass = null;
let wm = null;
@@ -109,15 +115,17 @@ function start() {
_defaultCssStylesheet = global.datadir + '/theme/gnome-shell.css';
loadTheme();
- let shellwm = global.window_manager;
- shellwm.takeover_keybinding('panel_main_menu');
- shellwm.connect('keybinding::panel_main_menu', function () {
- overview.toggle();
- });
- shellwm.takeover_keybinding('panel_run_dialog');
- shellwm.connect('keybinding::panel_run_dialog', function () {
- getRunDialog().open();
- });
+ if (global.session_type == Shell.SessionType.USER) {
+ let shellwm = global.window_manager;
+ shellwm.takeover_keybinding('panel_main_menu');
+ shellwm.connect('keybinding::panel_main_menu', function () {
+ overview.toggle();
+ });
+ shellwm.takeover_keybinding('panel_run_dialog');
+ shellwm.connect('keybinding::panel_run_dialog', function () {
+ getRunDialog().open();
+ });
+ }
// Set up stage hierarchy to group all UI actors under one container.
uiGroup = new Clutter.Group();
@@ -126,10 +134,14 @@ function start() {
global.overlay_group.reparent(uiGroup);
global.stage.add_actor(uiGroup);
- placesManager = new PlaceDisplay.PlacesManager();
+ if (global.session_type == Shell.SessionType.USER) {
+ placesManager = new PlaceDisplay.PlacesManager();
+ }
xdndHandler = new XdndHandler.XdndHandler();
ctrlAltTabManager = new CtrlAltTab.CtrlAltTabManager();
- overview = new Overview.Overview();
+ if (global.session_type == Shell.SessionType.USER) {
+ overview = new Overview.Overview();
+ }
chrome = new Chrome.Chrome();
magnifier = new Magnifier.Magnifier();
statusIconDispatcher = new StatusIconDispatcher.StatusIconDispatcher();
@@ -138,43 +150,61 @@ function start() {
messageTray = new MessageTray.MessageTray();
notificationDaemon = new NotificationDaemon.NotificationDaemon();
windowAttentionHandler = new WindowAttentionHandler.WindowAttentionHandler();
- telepathyClient = new TelepathyClient.Client();
- overview.init();
+ if (global.session_type == Shell.SessionType.USER) {
+ telepathyClient = new TelepathyClient.Client();
+ }
+
+ if (global.session_type == Shell.SessionType.USER) {
+ overview.init();
+ }
statusIconDispatcher.start(messageTray.actor);
_startDate = new Date();
- let recorderSettings = new Gio.Settings({ schema: 'org.gnome.shell.recorder' });
+ if (global.session_type == Shell.SessionType.USER) {
+ let recorderSettings = new Gio.Settings({ schema: 'org.gnome.shell.recorder' });
- global.screen.connect('toggle-recording', function() {
- if (recorder == null) {
- recorder = new Shell.Recorder({ stage: global.stage });
- }
+ global.screen.connect('toggle-recording', function() {
+ if (recorder == null) {
+ recorder = new Shell.Recorder({ stage: global.stage });
+ }
- if (recorder.is_recording()) {
- recorder.pause();
- } else {
- // read the parameters from GSettings always in case they have changed
- recorder.set_framerate(recorderSettings.get_int('framerate'));
- recorder.set_filename('shell-%d%u-%c.' + recorderSettings.get_string('file-extension'));
- let pipeline = recorderSettings.get_string('pipeline');
+ if (recorder.is_recording()) {
+ recorder.pause();
+ } else {
+ // read the parameters from GSettings always in case they have changed
+ recorder.set_framerate(recorderSettings.get_int('framerate'));
+ recorder.set_filename('shell-%d%u-%c.' + recorderSettings.get_string('file-extension'));
+ let pipeline = recorderSettings.get_string('pipeline');
- if (!pipeline.match(/^\s*$/))
- recorder.set_pipeline(pipeline);
- else
- recorder.set_pipeline(null);
+ if (!pipeline.match(/^\s*$/))
+ recorder.set_pipeline(pipeline);
+ else
+ recorder.set_pipeline(null);
- recorder.record();
- }
- });
+ recorder.record();
+ }
+ });
+ }
- global.screen.override_workspace_layout(Meta.ScreenCorner.TOPLEFT, false, -1, 1);
+ if (global.session_type == Shell.SessionType.LOGIN) {
+ global.screen.override_workspace_layout(Meta.ScreenCorner.TOPLEFT, false, 1, 1);
+ } else {
+ global.screen.override_workspace_layout(Meta.ScreenCorner.TOPLEFT, false, -1, 1);
+ }
// Provide the bus object for gnome-session to
// initiate logouts.
EndSessionDialog.init();
+ if (global.session_type == Shell.SessionType.LOGIN) {
+ loginDialog = new LoginDialog.LoginDialog();
+ loginDialog.connect('loaded', function() {
+ loginDialog.open();
+ });
+ }
+
// Attempt to become a PolicyKit authentication agent
PolkitAuthenticationAgent.init()
@@ -189,8 +219,10 @@ function start() {
panel.startStatusArea();
panel.startupAnimation();
- let display = global.screen.get_display();
- display.connect('overlay-key', Lang.bind(overview, overview.toggle));
+ if (global.session_type == Shell.SessionType.USER) {
+ let display = global.screen.get_display();
+ display.connect('overlay-key', Lang.bind(overview, overview.toggle));
+ }
global.stage.connect('captured-event', _globalKeyPressHandler);
@@ -488,73 +520,77 @@ function _relayout() {
hotCorners[i].destroy();
hotCorners = [];
+ if (global.session_type == Shell.SessionType.USER) {
+ let primary = global.get_primary_monitor();
+ for (let i = 0; i < monitors.length; i++) {
+ let monitor = monitors[i];
+ let isPrimary = (monitor.x == primary.x &&
+ monitor.y == primary.y &&
+ monitor.width == primary.width &&
+ monitor.height == primary.height);
- let primary = global.get_primary_monitor();
- for (let i = 0; i < monitors.length; i++) {
- let monitor = monitors[i];
- let isPrimary = (monitor.x == primary.x &&
- monitor.y == primary.y &&
- monitor.width == primary.width &&
- monitor.height == primary.height);
-
- let cornerX = monitor.x;
- let cornerY = monitor.y;
- if (St.Widget.get_default_direction() == St.TextDirection.RTL)
- cornerX += monitor.width;
+ let cornerX = monitor.x;
+ let cornerY = monitor.y;
+ if (St.Widget.get_default_direction() == St.TextDirection.RTL)
+ cornerX += monitor.width;
- let haveTopLeftCorner = true;
+ let haveTopLeftCorner = true;
- /* Check if we have a top left (right for RTL) corner.
- * I.e. if there is no monitor directly above or to the left(right) */
- let besideX;
- if (St.Widget.get_default_direction() == St.TextDirection.RTL)
- besideX = monitor.x + 1;
- else
- besideX = cornerX - 1;
- let besideY = cornerY;
- let aboveX = cornerX;
- let aboveY = cornerY - 1;
-
- for (let j = 0; j < monitors.length; j++) {
- if (i == j)
- continue;
- let otherMonitor = monitors[j];
- if (besideX >= otherMonitor.x &&
- besideX < otherMonitor.x + otherMonitor.width &&
- besideY >= otherMonitor.y &&
- besideY < otherMonitor.y + otherMonitor.height) {
- haveTopLeftCorner = false;
- break;
- }
- if (aboveX >= otherMonitor.x &&
- aboveX < otherMonitor.x + otherMonitor.width &&
- aboveY >= otherMonitor.y &&
- aboveY < otherMonitor.y + otherMonitor.height) {
- haveTopLeftCorner = false;
- break;
+ /* Check if we have a top left (right for RTL) corner.
+ * I.e. if there is no monitor directly above or to the left(right) */
+ let besideX;
+ if (St.Widget.get_default_direction() == St.TextDirection.RTL)
+ besideX = monitor.x + 1;
+ else
+ besideX = cornerX - 1;
+ let besideY = cornerY;
+ let aboveX = cornerX;
+ let aboveY = cornerY - 1;
+
+ for (let j = 0; j < monitors.length; j++) {
+ if (i == j)
+ continue;
+ let otherMonitor = monitors[j];
+ if (besideX >= otherMonitor.x &&
+ besideX < otherMonitor.x + otherMonitor.width &&
+ besideY >= otherMonitor.y &&
+ besideY < otherMonitor.y + otherMonitor.height) {
+ haveTopLeftCorner = false;
+ break;
+ }
+ if (aboveX >= otherMonitor.x &&
+ aboveX < otherMonitor.x + otherMonitor.width &&
+ aboveY >= otherMonitor.y &&
+ aboveY < otherMonitor.y + otherMonitor.height) {
+ haveTopLeftCorner = false;
+ break;
+ }
}
- }
- /* We only want hot corners where there is a natural top-left
- * corner, and on the primary monitor */
- if (!isPrimary && !haveTopLeftCorner)
- continue;
+ /* We only want hot corners where there is a natural top-left
+ * corner, and on the primary monitor */
+ if (!isPrimary && !haveTopLeftCorner)
+ continue;
- let corner = new Panel.HotCorner(isPrimary ? panel.button : null);
- hotCorners.push(corner);
- corner.actor.set_position(cornerX, cornerY);
- if (isPrimary)
- panel.setHotCorner(corner);
+ let corner = new Panel.HotCorner(isPrimary ? panel.button : null);
+ hotCorners.push(corner);
+ corner.actor.set_position(cornerX, cornerY);
+ if (isPrimary)
+ panel.setHotCorner(corner);
+ }
}
panel.relayout();
- overview.relayout();
- // To avoid updating the position and size of the workspaces
- // in the overview, we just hide the overview. The positions
- // will be updated when it is next shown.
- overview.hide();
+ if (global.session_type == Shell.SessionType.USER) {
+ overview.relayout();
+
+ // To avoid updating the position and size of the workspaces
+ // in the overview, we just hide the overview. The positions
+ // will be updated when it is next shown.
+ overview.hide();
+ }
}
function isWindowActorDisplayedOnWorkspace(win, workspaceIndex) {
@@ -597,6 +633,10 @@ function _globalKeyPressHandler(actor, event) {
return true;
}
+ if (global.session_type != Shell.SessionType.USER) {
+ return false;
+ }
+
// Other bindings are only available when the overview is up and
// no modal dialog is present.
if (!overview.visible || modalCount > 1)
@@ -796,7 +836,9 @@ function activateWindow(window, time, workspaceNum) {
window.activate(time);
}
- overview.hide();
+ if (global.session_type == Shell.SessionType.USER) {
+ overview.hide();
+ }
}
// TODO - replace this timeout with some system to guess when the user might
diff --git a/js/ui/messageTray.js b/js/ui/messageTray.js
index 1ae3fd7..1df6a54 100644
--- a/js/ui/messageTray.js
+++ b/js/ui/messageTray.js
@@ -213,14 +213,16 @@ FocusGrabber.prototype = {
this._capturedEventId = 0;
this._togglingFocusGrabMode = false;
- Main.overview.connect('showing', Lang.bind(this,
- function() {
- this._toggleFocusGrabMode();
- }));
- Main.overview.connect('hidden', Lang.bind(this,
- function() {
- this._toggleFocusGrabMode();
- }));
+ if (Main.overview) {
+ Main.overview.connect('showing', Lang.bind(this,
+ function() {
+ this._toggleFocusGrabMode();
+ }));
+ Main.overview.connect('hidden', Lang.bind(this,
+ function() {
+ this._toggleFocusGrabMode();
+ }));
+ }
},
grabFocus: function(actor) {
@@ -234,7 +236,7 @@ FocusGrabber.prototype = {
this._prevFocusedWindow = metaDisplay.focus_window;
this._prevKeyFocusActor = global.stage.get_key_focus();
- if (!Main.overview.visible)
+ if (!Main.overview || !Main.overview.visible)
global.set_stage_input_mode(Shell.StageInputMode.FOCUSED);
// Use captured-event to notice clicks outside the focused actor
@@ -1247,7 +1249,11 @@ MessageTray.prototype = {
this._notificationExpandedId = 0;
this._summaryBoxPointerState = State.HIDDEN;
this._summaryBoxPointerTimeoutId = 0;
- this._overviewVisible = Main.overview.visible;
+ if (Main.overview && Main.overview.visible) {
+ this._overviewVisible = true;
+ } else {
+ this._overviewVisible = false;
+ }
this._notificationRemoved = false;
this._reNotifyAfterHideNotification = null;
@@ -1260,26 +1266,28 @@ MessageTray.prototype = {
this._setSizePosition();
- Main.overview.connect('showing', Lang.bind(this,
- function() {
- this._overviewVisible = true;
- if (this._locked) {
- this._unsetClickedSummaryItem();
- this._unlock();
- } else {
- this._updateState();
- }
- }));
- Main.overview.connect('hiding', Lang.bind(this,
- function() {
- this._overviewVisible = false;
- if (this._locked) {
- this._unsetClickedSummaryItem();
- this._unlock();
- } else {
- this._updateState();
- }
- }));
+ if (Main.overview) {
+ Main.overview.connect('showing', Lang.bind(this,
+ function() {
+ this._overviewVisible = true;
+ if (this._locked) {
+ this._unsetClickedSummaryItem();
+ this._unlock();
+ } else {
+ this._updateState();
+ }
+ }));
+ Main.overview.connect('hiding', Lang.bind(this,
+ function() {
+ this._overviewVisible = false;
+ if (this._locked) {
+ this._unsetClickedSummaryItem();
+ this._unlock();
+ } else {
+ this._updateState();
+ }
+ }));
+ }
this._summaryItems = [];
// We keep a list of new summary items that were added to the summary since the last
diff --git a/js/ui/notificationDaemon.js b/js/ui/notificationDaemon.js
index 35eb581..a33870a 100644
--- a/js/ui/notificationDaemon.js
+++ b/js/ui/notificationDaemon.js
@@ -102,8 +102,10 @@ NotificationDaemon.prototype = {
Shell.WindowTracker.get_default().connect('notify::focus-app',
Lang.bind(this, this._onFocusAppChanged));
- Main.overview.connect('hidden',
- Lang.bind(this, this._onFocusAppChanged));
+ if (Main.overview) {
+ Main.overview.connect('hidden',
+ Lang.bind(this, this._onFocusAppChanged));
+ }
},
_iconForNotificationData: function(icon, hints, size) {
@@ -476,7 +478,7 @@ Source.prototype = {
this.notifications.length > 0)
return false;
- if (Main.overview.visible) {
+ if (Main.overview && Main.overview.visible) {
// We can't just connect to Main.overview's 'hidden' signal,
// because it's emitted *before* it calls popModal()...
let id = global.connect('notify::stage-input-mode', Lang.bind(this,
diff --git a/js/ui/panel.js b/js/ui/panel.js
index 7569f39..cbdf4d9 100644
--- a/js/ui/panel.js
+++ b/js/ui/panel.js
@@ -48,6 +48,14 @@ try {
log('NMApplet is not supported. It is possible that your NetworkManager version is too old');
}
+const LOGIN_TRAY_ICON_ORDER = ['a11y', 'display', 'keyboard', 'volume', 'battery'];
+const LOGIN_TRAY_ICON_SHELL_IMPLEMENTATION = {
+ 'a11y': imports.ui.status.accessibility.ATIndicator,
+ 'volume': imports.ui.status.volume.Indicator,
+ 'battery': imports.ui.status.power.Indicator,
+ 'keyboard': imports.ui.status.keyboard.XKBIndicator
+};
+
// To make sure the panel corners blend nicely with the panel,
// we draw background and borders the same way, e.g. drawing
// them as filled shapes from the outside inwards instead of
@@ -56,6 +64,8 @@ try {
// to blend border and background color together.
// For that purpose we use the following helper methods, taken
// from st-theme-node-drawing.c
+
+
function _norm(x) {
return Math.round(x / 255);
}
@@ -65,6 +75,7 @@ function _over(srcColor, dstColor) {
let dst = _premultiply(dstColor);
let result = new Clutter.Color();
+
result.alpha = src.alpha + _norm((255 - src.alpha) * dst.alpha);
result.red = src.red + _norm((255 - src.alpha) * dst.red);
result.green = src.green + _norm((255 - src.alpha) * dst.green);
@@ -270,15 +281,17 @@ AppMenuButton.prototype = {
this.menu.addMenuItem(this._quitMenu);
this._quitMenu.connect('activate', Lang.bind(this, this._onQuit));
- this._visible = !Main.overview.visible;
- if (!this._visible)
- this.actor.hide();
- Main.overview.connect('hiding', Lang.bind(this, function () {
- this.show();
- }));
- Main.overview.connect('showing', Lang.bind(this, function () {
- this.hide();
- }));
+ if (Main.overview) {
+ this._visible = !Main.overview.visible;
+ if (!this._visible)
+ this.actor.hide();
+ Main.overview.connect('hiding', Lang.bind(this, function () {
+ this.show();
+ }));
+ Main.overview.connect('showing', Lang.bind(this, function () {
+ this.hide();
+ }));
+ }
this._stop = true;
@@ -819,12 +832,22 @@ Panel.prototype = {
this._statusArea = {};
- Main.overview.connect('shown', Lang.bind(this, function () {
- this.actor.add_style_class_name('in-overview');
- }));
- Main.overview.connect('hiding', Lang.bind(this, function () {
- this.actor.remove_style_class_name('in-overview');
- }));
+ if (Main.overview) {
+ Main.overview.connect('shown', Lang.bind(this, function () {
+ this.actor.add_style_class_name('in-overview');
+ }));
+ Main.overview.connect('hiding', Lang.bind(this, function () {
+ this.actor.remove_style_class_name('in-overview');
+ }));
+ }
+
+ if (global.session_type == Shell.SessionType.LOGIN) {
+ this._tray_icon_order = LOGIN_TRAY_ICON_ORDER;
+ this._tray_icon_shell_implementation = LOGIN_TRAY_ICON_SHELL_IMPLEMENTATION;
+ } else {
+ this._tray_icon_order = STANDARD_TRAY_ICON_ORDER;
+ this._tray_icon_shell_implementation = STANDARD_TRAY_ICON_SHELL_IMPLEMENTATION;
+ }
this._leftPointerBarrier = 0;
this._rightPointerBarrier = 0;
@@ -908,39 +931,41 @@ Panel.prototype = {
this._rightBox.allocate(childBox, flags);
}));
- /* Button on the left side of the panel. */
- /* Translators: If there is no suitable word for "Activities" in your language, you can use the word for "Overview". */
- let label = new St.Label({ text: _("Activities") });
- this.button = new St.Button({ name: 'panelActivities',
- style_class: 'panel-button',
- reactive: true,
- can_focus: true });
- this._activities = this.button;
- this.button.set_child(label);
- this.button._delegate = this.button;
- this.button._xdndTimeOut = 0;
- this.button.handleDragOver = Lang.bind(this,
- function(source, actor, x, y, time) {
- if (source == Main.xdndHandler) {
- if (this.button._xdndTimeOut != 0)
- Mainloop.source_remove(this.button._xdndTimeOut);
- this.button._xdndTimeOut = Mainloop.timeout_add(BUTTON_DND_ACTIVATION_TIMEOUT,
- Lang.bind(this,
- function() {
- this._xdndShowOverview(actor);
- }));
- }
- });
- this._leftBox.add(this.button);
-
- // Synchronize the buttons pseudo classes with its corner
- this.button.connect('style-changed', Lang.bind(this,
- function(actor) {
- let rtl = actor.get_direction() == St.TextDirection.RTL;
- let corner = rtl ? this._rightCorner : this._leftCorner;
- let pseudoClass = actor.get_style_pseudo_class();
- corner.actor.set_style_pseudo_class(pseudoClass);
- }));
+ if (global.session_type == Shell.SessionType.USER) {
+ /* Button on the left side of the panel. */
+ /* Translators: If there is no suitable word for "Activities" in your language, you can use the word for "Overview". */
+ let label = new St.Label({ text: _("Activities") });
+ this.button = new St.Button({ name: 'panelActivities',
+ style_class: 'panel-button',
+ reactive: true,
+ can_focus: true });
+ this._activities = this.button;
+ this.button.set_child(label);
+ this.button._delegate = this.button;
+ this.button._xdndTimeOut = 0;
+ this.button.handleDragOver = Lang.bind(this,
+ function(source, actor, x, y, time) {
+ if (source == Main.xdndHandler) {
+ if (this.button._xdndTimeOut != 0)
+ Mainloop.source_remove(this.button._xdndTimeOut);
+ this.button._xdndTimeOut = Mainloop.timeout_add(BUTTON_DND_ACTIVATION_TIMEOUT,
+ Lang.bind(this,
+ function() {
+ this._xdndShowOverview(actor);
+ }));
+ }
+ });
+ this._leftBox.add(this.button);
+
+ // Synchronize the buttons pseudo classes with its corner
+ this.button.connect('style-changed', Lang.bind(this,
+ function(actor) {
+ let rtl = actor.get_direction() == St.TextDirection.RTL;
+ let corner = rtl ? this._rightCorner : this._leftCorner;
+ let pseudoClass = actor.get_style_pseudo_class();
+ corner.actor.set_style_pseudo_class(pseudoClass);
+ }));
+ }
this._hotCorner = null;
@@ -966,43 +991,50 @@ Panel.prototype = {
this._rightBox.add(this._trayBox);
this._rightBox.add(this._statusBox);
- this._userMenu = new StatusMenu.StatusMenuButton();
- this._userMenu.actor.name = 'panelStatus';
- this._rightBox.add(this._userMenu.actor);
-
- // Synchronize the buttons pseudo classes with its corner
- this._userMenu.actor.connect('style-changed', Lang.bind(this,
- function(actor) {
- let rtl = actor.get_direction() == St.TextDirection.RTL;
- let corner = rtl ? this._leftCorner : this._rightCorner;
- let pseudoClass = actor.get_style_pseudo_class();
- corner.actor.set_style_pseudo_class(pseudoClass);
- }));
+ if (global.session_type == Shell.SessionType.USER) {
+ this._userMenu = new StatusMenu.StatusMenuButton();
+ this._userMenu.actor.name = 'panelStatus';
+ this._rightBox.add(this._userMenu.actor);
+
+ // Synchronize the buttons pseudo classes with its corner
+ this._userMenu.actor.connect('style-changed', Lang.bind(this,
+ function(actor) {
+ let rtl = actor.get_direction() == St.TextDirection.RTL;
+ let corner = rtl ? this._leftCorner : this._rightCorner;
+ let pseudoClass = actor.get_style_pseudo_class();
+ corner.actor.set_style_pseudo_class(pseudoClass);
+ }));
+ }
Main.statusIconDispatcher.connect('status-icon-added', Lang.bind(this, this._onTrayIconAdded));
Main.statusIconDispatcher.connect('status-icon-removed', Lang.bind(this, this._onTrayIconRemoved));
- // 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
- // have the Overview act like a menu that allows the user to release the mouse on the activity the user wants
- // to switch to.
- this.button.connect('clicked', Lang.bind(this, function(b) {
- if (!Main.overview.animationInProgress) {
- this._hotCorner.maybeToggleOverviewOnClick();
- return true;
- } else {
- return false;
- }
- }));
- // In addition to pressing the button, the Overview can be entered and exited by other means, such as
- // pressing the System key, Alt+F1 or Esc. We want the button to be pressed in when the Overview is entered
- // and to be released when it is exited regardless of how it was triggered.
- Main.overview.connect('showing', Lang.bind(this, function() {
- this.button.checked = true;
- }));
- Main.overview.connect('hiding', Lang.bind(this, function() {
- this.button.checked = false;
- }));
+ if (global.session_type == Shell.SessionType.USER) {
+ // 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
+ // have the Overview act like a menu that allows the user to release the mouse on the activity the user wants
+ // to switch to.
+ this.button.connect('clicked', Lang.bind(this, function(b) {
+ if (!Main.overview.animationInProgress) {
+ this._hotCorner.maybeToggleOverviewOnClick();
+ return true;
+ } else {
+ return false;
+ }
+ }));
+ }
+
+ if (global.session_type == Shell.SessionType.USER) {
+ // In addition to pressing the button, the Overview can be entered and exited by other means, such as
+ // pressing the System key, Alt+F1 or Esc. We want the button to be pressed in when the Overview is entered
+ // and to be released when it is exited regardless of how it was triggered.
+ Main.overview.connect('showing', Lang.bind(this, function() {
+ this.button.checked = true;
+ }));
+ Main.overview.connect('hiding', Lang.bind(this, function() {
+ this.button.checked = false;
+ }));
+ }
Main.chrome.addActor(this.actor);
Main.chrome.addActor(this._leftCorner.actor, { affectsStruts: false,
@@ -1042,9 +1074,9 @@ Panel.prototype = {
},
startStatusArea: function() {
- for (let i = 0; i < STANDARD_TRAY_ICON_ORDER.length; i++) {
- let role = STANDARD_TRAY_ICON_ORDER[i];
- let constructor = STANDARD_TRAY_ICON_SHELL_IMPLEMENTATION[role];
+ for (let i = 0; i < this._tray_icon_order.length; i++) {
+ let role = this._tray_icon_order[i];
+ let constructor = this._tray_icon_shell_implementation[role];
if (!constructor) {
// This icon is not implemented (this is a bug)
continue;
@@ -1058,7 +1090,9 @@ Panel.prototype = {
// PopupMenuManager depends on menus being added in order for
// keyboard navigation
- this._menus.addMenu(this._userMenu.menu);
+ if (this._userMenu) {
+ this._menus.addMenu(this._userMenu.menu);
+ }
},
startupAnimation: function() {
@@ -1112,13 +1146,13 @@ Panel.prototype = {
_onTrayIconAdded: function(o, icon, role) {
icon.height = PANEL_ICON_SIZE;
- if (STANDARD_TRAY_ICON_SHELL_IMPLEMENTATION[role]) {
+ if (this._tray_icon_shell_implementation[role]) {
// This icon is legacy, and replaced by a Shell version
// Hide it
return;
}
// Figure out the index in our well-known order for this icon
- let position = STANDARD_TRAY_ICON_ORDER.indexOf(role);
+ let position = this._tray_icon_order.indexOf(role);
icon._rolePosition = position;
let children = this._trayBox.get_children();
let i;
diff --git a/js/ui/status/accessibility.js b/js/ui/status/accessibility.js
index 560042c..f1ffbf9 100644
--- a/js/ui/status/accessibility.js
+++ b/js/ui/status/accessibility.js
@@ -87,12 +87,14 @@ ATIndicator.prototype = {
let mouseKeys = this._buildItem(_("Mouse Keys"), A11Y_SCHEMA, KEY_MOUSE_KEYS_ENABLED);
this.menu.addMenuItem(mouseKeys);
- this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
- this.menu.addAction(_("Universal Access Settings"), function() {
- Main.overview.hide();
- let app = Shell.AppSystem.get_default().get_app('gnome-universal-access-panel.desktop');
- app.activate(-1);
- });
+ if (global.session_type == Shell.SessionType.USER) {
+ this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
+ this.menu.addAction(_("Universal Access Settings"), function() {
+ Main.overview.hide();
+ let app = Shell.AppSystem.get_default().get_app('gnome-universal-access-panel.desktop');
+ app.activate(-1);
+ });
+ }
},
_buildItemExtended: function(string, initial_value, writable, on_set) {
diff --git a/js/ui/status/keyboard.js b/js/ui/status/keyboard.js
index 3048da0..37af3a8 100644
--- a/js/ui/status/keyboard.js
+++ b/js/ui/status/keyboard.js
@@ -67,16 +67,18 @@ XKBIndicator.prototype = {
this._sync_config();
- this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
- this.menu.addAction(_("Show Keyboard Layout..."), Lang.bind(this, function() {
- Main.overview.hide();
- Util.spawn(['gkbd-keyboard-display', '-g', String(this._config.get_current_group() + 1)]);
- }));
- this.menu.addAction(_("Localization Settings"), function() {
- Main.overview.hide();
- let app = Shell.AppSystem.get_default().get_app('gnome-region-panel.desktop');
- app.activate(-1);
- });
+ if (global.session_type == Shell.SessionType.USER) {
+ this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
+ this.menu.addAction(_("Show Keyboard Layout..."), Lang.bind(this, function() {
+ Main.overview.hide();
+ Util.spawn(['gkbd-keyboard-display', '-g', String(this._config.get_current_group() + 1)]);
+ }));
+ this.menu.addAction(_("Localization Settings"), function() {
+ Main.overview.hide();
+ let app = Shell.AppSystem.get_default().get_app('gnome-region-panel.desktop');
+ app.activate(-1);
+ });
+ }
},
_sync_config: function() {
diff --git a/js/ui/status/power.js b/js/ui/status/power.js
index 1961702..222c699 100644
--- a/js/ui/status/power.js
+++ b/js/ui/status/power.js
@@ -78,13 +78,14 @@ Indicator.prototype = {
this._deviceSep = new PopupMenu.PopupSeparatorMenuItem();
this.menu.addMenuItem(this._deviceSep);
this._otherDevicePosition = 2;
- this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
- this.menu.addAction(_("Power Settings"),function() {
- Main.overview.hide();
- let app = Shell.AppSystem.get_default().get_app('gnome-power-panel.desktop');
- app.activate(-1);
- });
+ if (global.session_type == Shell.SessionType.USER) {
+ this.menu.addAction(_("Power Settings"),function() {
+ Main.overview.hide();
+ let app = Shell.AppSystem.get_default().get_app('gnome-power-panel.desktop');
+ app.activate(-1);
+ });
+ }
this._proxy.connect('Changed', Lang.bind(this, this._devicesChanged));
this._devicesChanged();
diff --git a/js/ui/status/volume.js b/js/ui/status/volume.js
index bd74cd9..bd669fe 100644
--- a/js/ui/status/volume.js
+++ b/js/ui/status/volume.js
@@ -60,12 +60,14 @@ Indicator.prototype = {
this.menu.addMenuItem(this._inputTitle);
this.menu.addMenuItem(this._inputSlider);
- this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
- this.menu.addAction(_("Sound Settings"), function() {
- Main.overview.hide();
- let app = Shell.AppSystem.get_default().get_app('gnome-sound-panel.desktop');
- app.activate(-1);
- });
+ if (global.session_type == Shell.SessionType.USER) {
+ this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
+ this.menu.addAction(_("Sound Settings"), function() {
+ Main.overview.hide();
+ let app = Shell.AppSystem.get_default().get_app('gnome-sound-panel.desktop');
+ app.activate(-1);
+ });
+ }
this.actor.connect('scroll-event', Lang.bind(this, this._onScrollEvent));
this._control.open();
diff --git a/js/ui/windowManager.js b/js/ui/windowManager.js
index a3e2918..aa1f24d 100644
--- a/js/ui/windowManager.js
+++ b/js/ui/windowManager.js
@@ -121,14 +121,16 @@ WindowManager.prototype = {
this.setKeybindingHandler('switch_group', Lang.bind(this, this._startAppSwitcher));
this.setKeybindingHandler('switch_panels', Lang.bind(this, this._startA11ySwitcher));
- Main.overview.connect('showing', Lang.bind(this, function() {
- for (let i = 0; i < this._dimmedWindows.length; i++)
- this._undimWindow(this._dimmedWindows[i], true);
- }));
- Main.overview.connect('hiding', Lang.bind(this, function() {
- for (let i = 0; i < this._dimmedWindows.length; i++)
- this._dimWindow(this._dimmedWindows[i], true);
- }));
+ if (Main.overview) {
+ Main.overview.connect('showing', Lang.bind(this, function() {
+ for (let i = 0; i < this._dimmedWindows.length; i++)
+ this._undimWindow(this._dimmedWindows[i], true);
+ }));
+ Main.overview.connect('hiding', Lang.bind(this, function() {
+ for (let i = 0; i < this._dimmedWindows.length; i++)
+ this._dimWindow(this._dimmedWindows[i], true);
+ }));
+ }
},
setKeybindingHandler: function(keybinding, handler){
@@ -150,7 +152,7 @@ WindowManager.prototype = {
},
_shouldAnimate : function(actor) {
- if (Main.overview.visible || this._animationsBlocked > 0)
+ if ((Main.overview && Main.overview.visible) || this._animationsBlocked > 0)
return false;
if (actor && (actor.meta_window.get_window_type() != Meta.WindowType.NORMAL))
return false;
@@ -250,14 +252,14 @@ WindowManager.prototype = {
if (shouldDim && !window._dimmed) {
window._dimmed = true;
this._dimmedWindows.push(window);
- if (!Main.overview.visible)
+ if (!Main.overview || !Main.overview.visible)
this._dimWindow(window, true);
} else if (!shouldDim && window._dimmed) {
window._dimmed = false;
this._dimmedWindows = this._dimmedWindows.filter(function(win) {
return win != window;
});
- if (!Main.overview.visible)
+ if (!Main.overview || !Main.overview.visible)
this._undimWindow(window, true);
}
},
@@ -573,7 +575,7 @@ WindowManager.prototype = {
if (indexToActivate != activeWorkspaceIndex)
global.screen.get_workspace_by_index(indexToActivate).activate(global.get_current_time());
- if (!Main.overview.visible)
+ if (!Main.overview || !Main.overview.visible)
this._workspaceSwitcherPopup.display(WorkspaceSwitcherPopup.UP, indexToActivate);
},
@@ -589,7 +591,7 @@ WindowManager.prototype = {
if (indexToActivate != activeWorkspaceIndex)
global.screen.get_workspace_by_index(indexToActivate).activate(global.get_current_time());
- if (!Main.overview.visible)
+ if (!Main.overview || !Main.overview.visible)
this._workspaceSwitcherPopup.display(WorkspaceSwitcherPopup.DOWN, indexToActivate);
},
@@ -602,7 +604,7 @@ WindowManager.prototype = {
if (indexToActivate != activeWorkspaceIndex)
global.screen.get_workspace_by_index(indexToActivate).activate(global.get_current_time());
- if (!Main.overview.visible)
+ if (!Main.overview || !Main.overview.visible)
this._workspaceSwitcherPopup.display(WorkspaceSwitcherPopup.UP, indexToActivate);
},
@@ -615,7 +617,7 @@ WindowManager.prototype = {
if (indexToActivate != activeWorkspaceIndex)
global.screen.get_workspace_by_index(indexToActivate).activate(global.get_current_time());
- if (!Main.overview.visible)
+ if (!Main.overview || !Main.overview.visible)
this._workspaceSwitcherPopup.display(WorkspaceSwitcherPopup.DOWN, indexToActivate);
}
};
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]