gnome-shell r97 - trunk/js/ui



Author: otaylor
Date: Mon Dec  1 19:51:43 2008
New Revision: 97
URL: http://svn.gnome.org/viewvc/gnome-shell?rev=97&view=rev

Log:
Redo tabs => spaces indentation change to not lose manual indentation

Revert most JS changes in commit:

    Fri Nov 28 20:12:20 2008 +0000
    Convert all JS style to be uniform, add Eclipse settings bits

Instead, just add 'indent-tabs-mode: nil' to the mode lines and convert
tabs to spaces. The indentation no longer exactly matches the Eclipse
settings, since they differ in some ways from the style we are trying
to achieve.

Modified:
   trunk/js/ui/appdisplay.js
   trunk/js/ui/button.js
   trunk/js/ui/main.js
   trunk/js/ui/overlay.js
   trunk/js/ui/panel.js
   trunk/js/ui/run_dialog.js
   trunk/js/ui/windowmanager.js

Modified: trunk/js/ui/appdisplay.js
==============================================================================
--- trunk/js/ui/appdisplay.js	(original)
+++ trunk/js/ui/appdisplay.js	Mon Dec  1 19:51:43 2008
@@ -1,4 +1,4 @@
-/* -*- mode: js2; js2-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil -*- */
+/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 
 const Signals = imports.signals;
 const Clutter = imports.gi.Clutter;
@@ -10,31 +10,31 @@
 const Meta = imports.gi.Meta;
 const Shell = imports.gi.Shell;
 
-//TODO - move this into GConf once we're not a plugin anymore
-//but have taken over metacity
-//This list is taken from GNOME Online popular applications
-//http://online.gnome.org/applications
-//but with nautilus removed
+// TODO - move this into GConf once we're not a plugin anymore
+// but have taken over metacity
+// This list is taken from GNOME Online popular applications
+// http://online.gnome.org/applications
+// but with nautilus removed
 const DEFAULT_APPLICATIONS = [
-                              'mozilla-firefox.desktop',
-                              'gnome-terminal.desktop',
-                              'evolution.desktop',
-                              'evince.desktop',
-                              'gedit.desktop',
-                              'mozilla-thunderbird.desktop',
-                              'totem.desktop',
-                              'gnome-file-roller.desktop',
-                              'rhythmbox.desktop',
-                              'epiphany.desktop',
-                              'xchat.desktop',
-                              'openoffice.org-1.9-writer.desktop',
-                              'emacs.desktop',
-                              'gnome-system-monitor.desktop',
-                              'openoffice.org-1.9-calc.desktop',
-                              'eclipse.desktop',
-                              'openoffice.org-1.9-impress.desktop',
-                              'vncviewer.desktop'
-                              ];
+    'mozilla-firefox.desktop',
+    'gnome-terminal.desktop',
+    'evolution.desktop',
+    'evince.desktop',
+    'gedit.desktop',
+    'mozilla-thunderbird.desktop',
+    'totem.desktop',
+    'gnome-file-roller.desktop',
+    'rhythmbox.desktop',
+    'epiphany.desktop',
+    'xchat.desktop',
+    'openoffice.org-1.9-writer.desktop',
+    'emacs.desktop',
+    'gnome-system-monitor.desktop',
+    'openoffice.org-1.9-calc.desktop',
+    'eclipse.desktop',
+    'openoffice.org-1.9-impress.desktop',
+    'vncviewer.desktop'
+];
 
 const APPDISPLAY_NAME_COLOR = new Clutter.Color();
 APPDISPLAY_NAME_COLOR.from_pixel(0xffffffff);
@@ -49,304 +49,305 @@
 const APPDISPLAY_PADDING = 4;
 
 function AppDisplayItem(node, width) {
-	this._init(node, width);
+    this._init(node, width);
 }
 
 AppDisplayItem.prototype = {
-_init: function(appinfo, width) {
-	let me = this;
-	this._appinfo = appinfo;
-
-	let name = appinfo.get_name();
-
-	let icontheme = Gtk.IconTheme.get_default();
-
-	this._group = new Clutter.Group({reactive: true,
-		width: width,
-		height: APPDISPLAY_HEIGHT});
-	this._group.connect('button-press-event', function(group, e) {
-		me.emit('activate');
-		return true;
-	});
-	this._bg = new Clutter.Rectangle({ color: APPDISPLAY_BACKGROUND_COLOR,
-		x: 0, y: 0, width: width, height: APPDISPLAY_HEIGHT });
-	this._group.add_actor(this._bg);
-
-	this._icon = new Clutter.Texture({ width: 48, height: 48, x: 0, y: 0 });
-	let gicon = appinfo.get_icon();
-	let path = null;
-	if (gicon != null) {
-		let iconinfo = icontheme.lookup_by_gicon(gicon, 48, Gtk.IconLookupFlags.NO_SVG);
-		if (iconinfo)
-			path = iconinfo.get_filename();
-	}
-
-	if (path)
-		this._icon.set_from_file(path);
-	this._group.add_actor(this._icon);
-
-	let comment = appinfo.get_description();
-	let text_width = width - me._icon.width + 4;
-	this._name = new Clutter.Label({ color: APPDISPLAY_NAME_COLOR,
-		font_name: "Sans 14px",
-		width: text_width,
-		ellipsize: Pango.EllipsizeMode.END,
-		text: name,
-		x: this._icon.width + 4,
-		y: 0});
-	this._group.add_actor(this._name);
-	this._comment = new Clutter.Label({ color: APPDISPLAY_COMMENT_COLOR,
-		font_name: "Sans 12px",
-		width: text_width,
-		ellipsize: Pango.EllipsizeMode.END,
-		text: comment,
-		x: this._name.x,
-		y: this._name.height + 4})
-	this._group.add_actor(this._comment);
-	this.actor = this._group;
-},
-launch: function() {
-    this._appinfo.launch([], null);
-},
-appinfo: function () {
-    return this._appinfo;
-},
-markSelected: function(isSelected) {
-   let color;
-   if (isSelected)
-       color = APPDISPLAY_SELECTED_BACKGROUND_COLOR;
-   else
-       color = APPDISPLAY_BACKGROUND_COLOR;
-   this._bg.color = color;
-}   
-}
+    _init: function(appinfo, width) {
+        let me = this;
+        this._appinfo = appinfo;
+
+        let name = appinfo.get_name();
+
+        let icontheme = Gtk.IconTheme.get_default();
+
+        this._group = new Clutter.Group({reactive: true,
+                                         width: width,
+                                         height: APPDISPLAY_HEIGHT});
+        this._group.connect('button-press-event', function(group, e) {
+            me.emit('activate');
+            return true;
+        });
+        this._bg = new Clutter.Rectangle({ color: APPDISPLAY_BACKGROUND_COLOR,
+                                           x: 0, y: 0,
+                                           width: width, height: APPDISPLAY_HEIGHT });
+        this._group.add_actor(this._bg);
+
+        this._icon = new Clutter.Texture({ width: 48, height: 48, x: 0, y: 0 });
+        let gicon = appinfo.get_icon();
+        let path = null;
+        if (gicon != null) {
+            let iconinfo = icontheme.lookup_by_gicon(gicon, 48, Gtk.IconLookupFlags.NO_SVG);
+            if (iconinfo)
+                path = iconinfo.get_filename();
+        }
+
+        if (path)
+            this._icon.set_from_file(path);
+        this._group.add_actor(this._icon);
+
+        let comment = appinfo.get_description();
+        let text_width = width - me._icon.width + 4;
+        this._name = new Clutter.Label({ color: APPDISPLAY_NAME_COLOR,
+                                     font_name: "Sans 14px",
+                                     width: text_width,
+                                     ellipsize: Pango.EllipsizeMode.END,
+                                     text: name,
+                                     x: this._icon.width + 4,
+                                     y: 0});
+        this._group.add_actor(this._name);
+        this._comment = new Clutter.Label({ color: APPDISPLAY_COMMENT_COLOR,
+                                             font_name: "Sans 12px",
+                                             width: text_width,
+                                             ellipsize: Pango.EllipsizeMode.END,
+                                             text: comment,
+                                             x: this._name.x,
+                                             y: this._name.height + 4})
+        this._group.add_actor(this._comment);
+        this.actor = this._group;
+    },
+    launch: function() {
+        this._appinfo.launch([], null);
+    },
+    appinfo: function () {
+        return this._appinfo;
+    },
+    markSelected: function(isSelected) {
+       let color;
+       if (isSelected)
+           color = APPDISPLAY_SELECTED_BACKGROUND_COLOR;
+       else
+           color = APPDISPLAY_BACKGROUND_COLOR;
+       this._bg.color = color;
+    }
+};
+
 Signals.addSignalMethods(AppDisplayItem.prototype);
 
 function AppDisplay(x, y, width, height) {
-	this._init(x, y, width, height);
+    this._init(x, y, width, height);
 }
 
 AppDisplay.prototype = {
-_init : function(x, y, width, height) {
-	let me = this;
-	let global = Shell.Global.get();
-	this._search = '';
-	this._x = x;
-	this._y = y;
-	this._width = width;
-	this._height = height;
-	this._appmonitor = new Shell.AppMonitor();
-	this._appsStale = true;
-	this._appmonitor.connect('changed', function(mon) {
-		me._appsStale = true;
-	});
-	this._grid = new Tidy.Grid({x: x, y: y, width: width, height: height});
-	global.stage.add_actor(this._grid);
-	this._appset = {}; // Map<appid, appinfo>
-	this._displayed = {} // Map<appid, AppDisplay>
-	this._selectedIndex = -1;
-	this._max_items = this._height / (APPDISPLAY_HEIGHT + APPDISPLAY_PADDING);
-},
-
-_refreshCache: function() {
-	let me = this;
-
-	if (!this._appsStale)
-		return;
-	for (id in this._displayed)
-		this._displayed[id].destroy();
-	this._appset = {};
-	this._displayed = {};
-	this._selectedIndex = -1;
-	let apps = Gio.app_info_get_all();
-	for (let i = 0; i < apps.length; i++) {
-		let appinfo = apps[i];
-		let appid = appinfo.get_id();
-		this._appset[appid] = appinfo;
-	}
-	this._appsStale = false;
-},
-
-_removeItem: function(appid) {
-	let item = this._displayed[appid];
-	let group = item.actor;
-	group.destroy();
-	delete this._displayed[appid];
-	
-},
-
-_removeAll: function() {
-	for (appid in this._displayed)
-		this._removeItem(appid);
-},
-
-_setDefaultList: function() {
-	this._removeAll();
-	let added = 0;
-	for (let i = 0; i < DEFAULT_APPLICATIONS.length && added < this._max_items; i++) {
-		let appid = DEFAULT_APPLICATIONS[i];
-		let appinfo = this._appset[appid];
-		if (appinfo) {
-			this._filterAdd(appid);
-			added += 1;
-		}
-	}
-},
-
-_getNDisplayed: function() {
-    // Is there a better way to do .size() ?
-    let c = 0; for (i in this._displayed) { c += 1; };
-    return c;
-},
-
-_filterAdd: function(appid) {
-	let me = this;
-
-	let appinfo = this._appset[appid];
-	let name = appinfo.get_name();
-	let index = this._getNDisplayed();
-
-	let appdisplay = new AppDisplayItem(appinfo, this._width);
-	appdisplay.connect('activate', function() {
-	    appdisplay.launch();
-		me.emit('activated');
-	});
-	let group = appdisplay.actor;
-	this._grid.add_actor(group);
-	this._displayed[appid] = appdisplay;
-},
-
-_filterRemove: function(appid) {
-	// In the future, do some sort of fade out or other effect here
-	let item = this._displayed[appid];
-	this._removeItem(item);
-},
-
-_appinfoMatches: function(appinfo, search) {
-	if (search == null || search == '')
-		return true;
-	let name = appinfo.get_name().toLowerCase();
-	if (name.indexOf(search) >= 0)
-		return true;
-	let description = appinfo.get_description();
-	if (description) {
-		description = description.toLowerCase();
-		if (description.indexOf(search) >= 0)
-			return true;
-	}
-	let exec = appinfo.get_executable().toLowerCase();
-	if (exec.indexOf(search) >= 0)
-		return true;
-	return false;
-},
-
-_sortApps: function(appids) {
-	let me = this;
-	return appids.sort(function (a,b) {
-		let appA = me._appset[a];
-		let appB = me._appset[b];
-		return appA.get_name().localeCompare(appB.get_name());
-	});
-},
-
-_doSearchFilter: function() {
-	this._removeAll();
-	let matchedApps = [];
-	for (appid in this._appset) {
-		if (matchedApps.length >= this._max_items)
-			break;
-		if (this._displayed[appid])
-			continue;
-		let app = this._appset[appid];
-		if (this._appinfoMatches(app, this._search))
-			matchedApps.push(appid);
-	}
-	this._sortApps(matchedApps);
-	for (let i = 0; i < matchedApps.length; i++) {
-		this._filterAdd(matchedApps[i]);
-	}
-},
-
-_redisplay: function() {
-	this._refreshCache();
-	if (!this._search)
-		this._setDefaultList();
-	else
-		this._doSearchFilter();
-},
-
-setSearch: function(text) {
-	this._search = text.toLowerCase();
-	this._redisplay();
-},
-
-_findDisplayedByIndex: function(index) {
-    let displayedActors = this._grid.get_children();
-    let actor = displayedActors[index];
-    return this._findDisplayedByActor(actor);
-},
+    _init : function(x, y, width, height) {
+        let me = this;
+        let global = Shell.Global.get();
+        this._search = '';
+        this._x = x;
+        this._y = y;
+        this._width = width;
+        this._height = height;
+        this._appmonitor = new Shell.AppMonitor();
+        this._appsStale = true;
+        this._appmonitor.connect('changed', function(mon) {
+            me._appsStale = true;
+        });
+        this._grid = new Tidy.Grid({x: x, y: y, width: width, height: height});
+        global.stage.add_actor(this._grid);
+        this._appset = {}; // Map<appid, appinfo>
+        this._displayed = {}; // Map<appid, AppDisplay>
+        this._selectedIndex = -1;
+        this._max_items = this._height / (APPDISPLAY_HEIGHT + APPDISPLAY_PADDING);
+    },
+
+    _refreshCache: function() {
+        let me = this;
+
+        if (!this._appsStale)
+            return;
+        for (id in this._displayed)
+            this._displayed[id].destroy();
+        this._appset = {};
+        this._displayed = {};
+        this._selectedIndex = -1;
+        let apps = Gio.app_info_get_all();
+        for (let i = 0; i < apps.length; i++) {
+            let appinfo = apps[i];
+            let appid = appinfo.get_id();
+            this._appset[appid] = appinfo;
+        }
+        this._appsStale = false;
+    },
 
-_findDisplayedByActor: function(actor) {
-    for (appid in this._displayed) {
+    _removeItem: function(appid) {
         let item = this._displayed[appid];
-        if (item.actor == actor) {
-            return item;
+        let group = item.actor;
+        group.destroy();
+        delete this._displayed[appid];
+    },
+
+    _removeAll: function() {
+        for (appid in this._displayed)
+            this._removeItem(appid);
+     },
+
+    _setDefaultList: function() {
+        this._removeAll();
+        let added = 0;
+        for (let i = 0; i < DEFAULT_APPLICATIONS.length && added < this._max_items; i++) {
+            let appid = DEFAULT_APPLICATIONS[i];
+            let appinfo = this._appset[appid];
+            if (appinfo) {
+              this._filterAdd(appid);
+              added += 1;
+            }
+        }
+    },
+
+    _getNDisplayed: function() {
+        // Is there a better way to do .size() ?
+        let c = 0; for (i in this._displayed) { c += 1; };
+        return c;
+    },
+
+    _filterAdd: function(appid) {
+        let me = this;
+
+        let appinfo = this._appset[appid];
+        let name = appinfo.get_name();
+        let index = this._getNDisplayed();
+
+        let appdisplay = new AppDisplayItem(appinfo, this._width);
+        appdisplay.connect('activate', function() {
+            appdisplay.launch();
+            me.emit('activated');
+        });
+        let group = appdisplay.actor;
+        this._grid.add_actor(group);
+        this._displayed[appid] = appdisplay;
+    },
+
+    _filterRemove: function(appid) {
+        // In the future, do some sort of fade out or other effect here
+        let item = this._displayed[appid];
+        this._removeItem(item);
+    },
+
+    _appinfoMatches: function(appinfo, search) {
+        if (search == null || search == '')
+            return true;
+        let name = appinfo.get_name().toLowerCase();
+        if (name.indexOf(search) >= 0)
+            return true;
+        let description = appinfo.get_description();
+        if (description) {
+            description = description.toLowerCase();
+            if (description.indexOf(search) >= 0)
+                return true;
+        }
+        let exec = appinfo.get_executable().toLowerCase();
+        if (exec.indexOf(search) >= 0)
+            return true;
+        return false;
+    },
+
+    _sortApps: function(appids) {
+        let me = this;
+        return appids.sort(function (a,b) {
+            let appA = me._appset[a];
+            let appB = me._appset[b];
+            return appA.get_name().localeCompare(appB.get_name());
+        });
+    },
+
+    _doSearchFilter: function() {
+        this._removeAll();
+        let matchedApps = [];
+        for (appid in this._appset) {
+            if (matchedApps.length >= this._max_items)
+                break;
+            if (this._displayed[appid])
+                continue;
+            let app = this._appset[appid];
+            if (this._appinfoMatches(app, this._search))
+                matchedApps.push(appid);
         }
-    }    
-    return null;
-},
-
-searchActivate: function() {
-    if (this._selectedIndex != -1) {
-        let selected = this._findDisplayedByIndex(this._selectedIndex);
-        selected.launch();
+        this._sortApps(matchedApps);
+        for (let i = 0; i < matchedApps.length; i++) {
+            this._filterAdd(matchedApps[i]);
+        }
+    },
+
+    _redisplay: function() {
+        this._refreshCache();
+        if (!this._search)
+            this._setDefaultList();
+        else
+            this._doSearchFilter();
+    },
+
+    setSearch: function(text) {
+        this._search = text.toLowerCase();
+        this._redisplay();
+    },
+
+    _findDisplayedByIndex: function(index) {
+        let displayedActors = this._grid.get_children();
+        let actor = displayedActors[index];
+        return this._findDisplayedByActor(actor);
+    },
+
+    _findDisplayedByActor: function(actor) {
+        for (appid in this._displayed) {
+            let item = this._displayed[appid];
+            if (item.actor == actor) {
+                return item;
+            }
+        }
+        return null;
+    },
+
+    searchActivate: function() {
+        if (this._selectedIndex != -1) {
+            let selected = this._findDisplayedByIndex(this._selectedIndex);
+            selected.launch();
+            this.emit('activated');
+            return;
+        }
+        let displayedActors = this._grid.get_children();
+        if (displayedActors.length != 1)
+            return;
+        let selectedActor = displayedActors[0];
+        let selectedMenuItem = this._findDisplayedByActor(selectedActor);
+        selectedMenuItem.launch();
         this.emit('activated');
-        return;
-    }     
-    let displayedActors = this._grid.get_children();
-    if (displayedActors.length != 1)
-        return;
-    let selectedActor = displayedActors[0];
-    let selectedMenuItem = this._findDisplayedByActor(selectedActor);
-    selectedMenuItem.launch();
-    this.emit('activated');
-},
-
-_selectIndex: function(index) {
-    if (this._selectedIndex != -1) {
-        let prev = this._findDisplayedByIndex(this._selectedIndex);
-        log("demarking " + prev);        
-        prev.markSelected(false);
+    },
+
+    _selectIndex: function(index) {
+        if (this._selectedIndex != -1) {
+            let prev = this._findDisplayedByIndex(this._selectedIndex);
+            log("demarking " + prev);
+            prev.markSelected(false);
+        }
+        this._selectedIndex = index;
+        let item = this._findDisplayedByIndex(index);
+        log("marking " + item);
+        item.markSelected(true);
+    },
+
+    selectUp: function() {
+        let prev = this._selectedIndex-1;
+        if (prev < 0)
+            return;
+        this._selectIndex(prev);
+    },
+
+    selectDown: function() {
+        let next = this._selectedIndex+1;
+        let nDisplayed = this._getNDisplayed();
+        if (next >= nDisplayed)
+            return;
+        this._selectIndex(next);
+    },
+
+    show: function() {
+        this._redisplay();
+        this._grid.show();
+    },
+
+    hide: function() {
+        this._grid.hide();
     }
-    this._selectedIndex = index;
-    let item = this._findDisplayedByIndex(index);
-    log("marking " + item);    
-    item.markSelected(true);
-},
-
-selectUp: function() {
-    let prev = this._selectedIndex-1;
-    if (prev < 0)
-        return;
-    this._selectIndex(prev);
-},
-
-selectDown: function() {
-    let next = this._selectedIndex+1;
-    let nDisplayed = this._getNDisplayed();
-    if (next >= nDisplayed)
-        return;
-    this._selectIndex(next);
-},
-
-show: function() {
-	this._redisplay();
-	this._grid.show();
-},
+};
 
-hide: function() {
-	this._grid.hide();
-}
-}
 Signals.addSignalMethods(AppDisplay.prototype);
-

Modified: trunk/js/ui/button.js
==============================================================================
--- trunk/js/ui/button.js	(original)
+++ trunk/js/ui/button.js	Mon Dec  1 19:51:43 2008
@@ -1,4 +1,4 @@
-/* -*- mode: js2; js2-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil -*- */
+/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 
 const Clutter = imports.gi.Clutter;
 const Tweener = imports.tweener.tweener;
@@ -9,7 +9,7 @@
 const DEFAULT_PRESSED_BUTTON_COLOR = new Clutter.Color();
 DEFAULT_PRESSED_BUTTON_COLOR.from_pixel(0xccbbaaff);
 
-//Time for animation making the button darker
+// Time for animation making the button darker
 const ANIMATION_TIME = 0.3;
 
 const NO_OPACITY = 0;
@@ -23,95 +23,95 @@
 }
 
 Button.prototype = {
-_init : function(text, buttonColor, pressedButtonColor, staysPressed, minWidth, minHeight) {
-    let me = this;
-    this._buttonColor = buttonColor
-    if (buttonColor == null)
-        this._buttonColor = DEFAULT_BUTTON_COLOR;
-
-    this._pressedButtonColor = pressedButtonColor
-    if (pressedButtonColor == null)
-        this._pressedButtonColor = DEFAULT_PRESSED_BUTTON_COLOR;
-
-    if (staysPressed == null)
-        staysPressed = false;
-    if (minWidth == null)
-        minWidth = 0;
-    if (minHeight == null)
-        minHeight = 0;
-
-    // if staysPressed is true, this.active will be true past the first release of a button, untill a subsequent one (the button
-    // is unpressed) or untill release() is called explicitly
-    this._active = false;
-    this._isBetweenPressAndRelease = false;
-    this._mouseIsOverButton = false;
-
-    this.button = new Clutter.Group({reactive: true});
-    this._background = new Clutter.Rectangle({ color: this._buttonColor});
-    this._pressedBackground = new Clutter.Rectangle({ color: this._pressedButtonColor, opacity: NO_OPACITY});
-    this._label = new Clutter.Label({ font_name: "Sans Bold 16px",
-        text: text});
-    this._label.set_position(5, 5);
-    let backgroundWidth = Math.max(this._label.get_width()+10, minWidth);
-    let backgroundHeight = Math.max(this._label.get_height()+10, minHeight);
-    this._background.set_width(backgroundWidth)
-    this._background.set_height(backgroundHeight)
-    this._pressedBackground.set_width(backgroundWidth)
-    this._pressedBackground.set_height(backgroundHeight)
-    this.button.add_actor(this._background);
-    this.button.add_actor(this._pressedBackground);
-    this.button.add_actor(this._label);
-    this.button.connect('button-press-event',
-        function(o, event) {
-            me._isBetweenPressAndRelease = true;
-            Tweener.addTween(me._pressedBackground,
-                { time: ANIMATION_TIME,
-                  opacity: FULL_OPACITY,
-                  transition: "linear"
-                });
-            return false;
-    });
-    this.button.connect('button-release-event',
-        function(o, event) {
-            me._isBetweenPressAndRelease = false;
-            if (!staysPressed || me._active) {
-                me.release();
-            } else {
-                me._active = true;
-            }
-            return false;
-    });
-    this.button.connect('enter-event',
-        function(o, event) {
-            me._mouseIsOverButton = true;
-            if (!me._active) {
-                Tweener.removeTweens(me._pressedBackground);
-                me._pressedBackground.set_opacity(PARTIAL_OPACITY);
-            }
-            return false;
-    });
-    this.button.connect('leave-event',
-        function(o, event) {
-            me._isBetweenPressAndRelease = false;
-            me._mouseIsOverButton = false;
-            if (!me._active) {
-                Tweener.removeTweens(me._pressedBackground);
-                me._pressedBackground.set_opacity(NO_OPACITY);
-            }
-            return false;
-    });
-},
+    _init : function(text, buttonColor, pressedButtonColor, staysPressed, minWidth, minHeight) {
+        let me = this;
+
+        this._buttonColor = buttonColor
+        if (buttonColor == null)
+            this._buttonColor = DEFAULT_BUTTON_COLOR;
+
+        this._pressedButtonColor = pressedButtonColor
+        if (pressedButtonColor == null)
+            this._pressedButtonColor = DEFAULT_PRESSED_BUTTON_COLOR;
+
+        if (staysPressed == null)
+            staysPressed = false;
+        if (minWidth == null)
+            minWidth = 0;
+        if (minHeight == null)
+            minHeight = 0;
 
-release : function() {
-    if (!this._isBetweenPressAndRelease) {
+        // if staysPressed is true, this.active will be true past the first release of a button, untill a subsequent one (the button
+        // is unpressed) or untill release() is called explicitly
         this._active = false;
-        Tweener.removeTweens(this._pressedBackground);
-        if (this._mouseIsOverButton) {
-            this._pressedBackground.set_opacity(PARTIAL_OPACITY);
-        } else {
-            this._pressedBackground.set_opacity(NO_OPACITY);
+        this._isBetweenPressAndRelease = false;
+        this._mouseIsOverButton = false;
+
+        this.button = new Clutter.Group({reactive: true});
+        this._background = new Clutter.Rectangle({ color: this._buttonColor});
+        this._pressedBackground = new Clutter.Rectangle({ color: this._pressedButtonColor, opacity: NO_OPACITY});
+        this._label = new Clutter.Label({ font_name: "Sans Bold 16px",
+                                         text: text});
+        this._label.set_position(5, 5);
+        let backgroundWidth = Math.max(this._label.get_width()+10, minWidth);
+        let backgroundHeight = Math.max(this._label.get_height()+10, minHeight);
+        this._background.set_width(backgroundWidth)
+        this._background.set_height(backgroundHeight)
+        this._pressedBackground.set_width(backgroundWidth)
+        this._pressedBackground.set_height(backgroundHeight)
+        this.button.add_actor(this._background);
+        this.button.add_actor(this._pressedBackground);
+        this.button.add_actor(this._label);
+        this.button.connect('button-press-event',
+            function(o, event) {
+                me._isBetweenPressAndRelease = true;
+                Tweener.addTween(me._pressedBackground,
+                                { time: ANIMATION_TIME,
+                                  opacity: FULL_OPACITY,
+                                  transition: "linear"
+                                });
+                return false;
+            });
+        this.button.connect('button-release-event',
+            function(o, event) {
+                me._isBetweenPressAndRelease = false;
+                if (!staysPressed || me._active) {
+                    me.release();
+                } else {
+                    me._active = true;
+                }
+                return false;
+            });
+        this.button.connect('enter-event',
+            function(o, event) {
+                me._mouseIsOverButton = true;
+                if (!me._active) {
+                    Tweener.removeTweens(me._pressedBackground);
+                    me._pressedBackground.set_opacity(PARTIAL_OPACITY);
+                }
+                return false;
+            });
+        this.button.connect('leave-event',
+            function(o, event) {
+                me._isBetweenPressAndRelease = false;
+                me._mouseIsOverButton = false;
+                if (!me._active) {
+                    Tweener.removeTweens(me._pressedBackground);
+                    me._pressedBackground.set_opacity(NO_OPACITY);
+                }
+                return false;
+            });
+    },
+
+    release : function() {
+        if (!this._isBetweenPressAndRelease) {
+            this._active = false;
+            Tweener.removeTweens(this._pressedBackground);
+            if (this._mouseIsOverButton) {
+                this._pressedBackground.set_opacity(PARTIAL_OPACITY);
+            } else {
+                this._pressedBackground.set_opacity(NO_OPACITY);
+            }
         }
     }
-}
-}
-
+};

Modified: trunk/js/ui/main.js
==============================================================================
--- trunk/js/ui/main.js	(original)
+++ trunk/js/ui/main.js	Mon Dec  1 19:51:43 2008
@@ -1,4 +1,4 @@
-/* -*- mode: js2; js2-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil -*- */
+/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 
 const Clutter = imports.gi.Clutter;
 const Shell = imports.gi.Shell;
@@ -18,67 +18,67 @@
 let run_dialog = null;
 let wm = null;
 
-//The "FrameTicker" object is an object used to feed new frames to Tweener
-//so it can update values and redraw. The default frame ticker for
-//Tweener just uses a simple timeout at a fixed frame rate and has no idea
-//of "catching up" by dropping frames.
-
-//We substitute it with custom frame ticker here that connects Tweener to
-//a Clutter.TimeLine. Now, Clutter.Timeline itself isn't a whole lot more
-//sophisticated than a simple timeout at a fixed frame rate, but at least
-//it knows how to drop frames. (See HippoAnimationManager for a more
-//sophisticated view of continous time updates; even better is to pay
-//attention to the vertical vblank and sync to that when possible.)
-
+// The "FrameTicker" object is an object used to feed new frames to Tweener
+// so it can update values and redraw. The default frame ticker for
+// Tweener just uses a simple timeout at a fixed frame rate and has no idea
+// of "catching up" by dropping frames.
+//
+// We substitute it with custom frame ticker here that connects Tweener to
+// a Clutter.TimeLine. Now, Clutter.Timeline itself isn't a whole lot more
+// sophisticated than a simple timeout at a fixed frame rate, but at least
+// it knows how to drop frames. (See HippoAnimationManager for a more
+// sophisticated view of continous time updates; even better is to pay
+// attention to the vertical vblank and sync to that when possible.)
+//
 function ClutterFrameTicker() {
     this._init();
 }
 
 ClutterFrameTicker.prototype = {
-TARGET_FRAME_RATE : 60,
+    TARGET_FRAME_RATE : 60,
 
-_init : function() {
-    // We don't have a finite duration; tweener will tell us to stop
-    // when we need to stop, so use 1000 seconds as "infinity"
-    this._timeline = new Clutter.Timeline({ fps: this.TARGET_FRAME_RATE,
-        duration: 1000*1000 });
-    this._frame = 0;
+    _init : function() {
+        // We don't have a finite duration; tweener will tell us to stop
+        // when we need to stop, so use 1000 seconds as "infinity"
+        this._timeline = new Clutter.Timeline({ fps: this.TARGET_FRAME_RATE,
+                                                duration: 1000*1000 });
+        this._frame = 0;
 
-    let me = this;
-    this._timeline.connect('new-frame',
+        let me = this;
+        this._timeline.connect('new-frame',
             function(timeline, frame) {
-        me._onNewFrame(frame);
-    });
-},
-
-_onNewFrame : function(frame) {
-    // Unfortunately the interface to to send a new frame to tweener
-    // is a simple "next frame" and there is no provision for signaling
-    // that frames have been skipped or just telling it the new time.
-    // But what it actually does internally is just:
-    //
-    //  _currentTime += 1000/_ticker.FRAME_RATE;
-    //
-    // So by dynamically adjusting the value of FRAME_RATE we can trick
-    // it into dealing with dropped frames.
-
-    let delta = frame - this._frame;
-    if (delta == 0)
-        this.FRAME_RATE = this.TARGET_FRAME_RATE;
-    else
-        this.FRAME_RATE = this.TARGET_FRAME_RATE / delta;
-    this._frame = frame;
-    this.emit('prepare-frame');
-},
-
-start : function() {
-    this._timeline.start();
-},
-
-stop : function() {
-    this._timeline.stop();
-    this._frame = 0;
-}
+                me._onNewFrame(frame);
+            });
+    },
+
+    _onNewFrame : function(frame) {
+        // Unfortunately the interface to to send a new frame to tweener
+        // is a simple "next frame" and there is no provision for signaling
+        // that frames have been skipped or just telling it the new time.
+        // But what it actually does internally is just:
+        //
+        //  _currentTime += 1000/_ticker.FRAME_RATE;
+        //
+        // So by dynamically adjusting the value of FRAME_RATE we can trick
+        // it into dealing with dropped frames.
+
+        let delta = frame - this._frame;
+        if (delta == 0)
+            this.FRAME_RATE = this.TARGET_FRAME_RATE;
+        else
+            this.FRAME_RATE = this.TARGET_FRAME_RATE / delta;
+        this._frame = frame;
+        this.emit('prepare-frame');
+    },
+
+    start : function() {
+        this._timeline.start();
+    },
+
+    stop : function() {
+        this._timeline.stop();
+        this._frame = 0;
+    }
 };
 
 Signals.addSignalMethods(ClutterFrameTicker.prototype);
@@ -121,9 +121,9 @@
     wm = new WindowManager.WindowManager();
 }
 
-//Used to go into a mode where all keyboard and mouse input goes to
-//the stage. Returns true if we successfully grabbed the keyboard and
-//went modal, false otherwise
+// Used to go into a mode where all keyboard and mouse input goes to
+// the stage. Returns true if we successfully grabbed the keyboard and
+// went modal, false otherwise
 function startModal() {
     let global = Shell.Global.get();
 

Modified: trunk/js/ui/overlay.js
==============================================================================
--- trunk/js/ui/overlay.js	(original)
+++ trunk/js/ui/overlay.js	Mon Dec  1 19:51:43 2008
@@ -1,4 +1,4 @@
-/* -*- mode: js2; js2-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil -*- */
+/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 
 const Signals = imports.signals;
 const Mainloop = imports.mainloop;
@@ -23,27 +23,27 @@
 const SIDESHOW_TEXT_COLOR = new Clutter.Color();
 SIDESHOW_TEXT_COLOR.from_pixel(0xffffffff);
 
-//Time for initial animation going into overlay mode
+// Time for initial animation going into overlay mode
 const ANIMATION_TIME = 0.5;
 
-//How much to scale the desktop down by in overlay mode
+// How much to scale the desktop down by in overlay mode
 const DESKTOP_SCALE = 0.75;
 
-//Windows are slightly translucent in the overlay mode
+// Windows are slightly translucent in the overlay mode
 const WINDOW_OPACITY = 0.9 * 255;
 
-//Define a layout scheme for small window counts. For larger
-//counts we fall back to an algorithm. We need more schemes here
-//unless we have a really good algorithm.
-
-//Each triplet is [xCenter, yCenter, scale] where the scale
-//is relative to the width of the desktop.
+// Define a layout scheme for small window counts. For larger
+// counts we fall back to an algorithm. We need more schemes here
+// unless we have a really good algorithm.
+//
+// Each triplet is [xCenter, yCenter, scale] where the scale
+// is relative to the width of the desktop.
 const POSITIONS = {
-        1: [[0.5, 0.5, 0.8]],
-        2: [[0.25, 0.5, 0.4], [0.75, 0.5, 0.4]],
-        3: [[0.25, 0.25, 0.33],  [0.75, 0.25, 0.33],  [0.5, 0.75, 0.33]],
-        4: [[0.25, 0.25, 0.33],   [0.75, 0.25, 0.33], [0.75, 0.75, 0.33], [0.25, 0.75, 0.33]],
-        5: [[0.165, 0.25, 0.28], [0.495, 0.25, 0.28], [0.825, 0.25, 0.28], [0.25, 0.75, 0.4], [0.75, 0.75, 0.4]]
+    1: [[0.5, 0.5, 0.8]],
+    2: [[0.25, 0.5, 0.4], [0.75, 0.5, 0.4]],
+    3: [[0.25, 0.25, 0.33],  [0.75, 0.25, 0.33],  [0.5, 0.75, 0.33]],
+    4: [[0.25, 0.25, 0.33],   [0.75, 0.25, 0.33], [0.75, 0.75, 0.33], [0.25, 0.75, 0.33]],
+    5: [[0.165, 0.25, 0.28], [0.495, 0.25, 0.28], [0.825, 0.25, 0.28], [0.25, 0.75, 0.4], [0.75, 0.75, 0.4]]
 };
 
 function Sideshow(width) {
@@ -51,95 +51,95 @@
 }
 
 Sideshow.prototype = {
-_init : function(width) {
-    let me = this;
+    _init : function(width) {
+        let me = this;
 
-    let global = Shell.Global.get();
-    this._group = new Clutter.Group();
-    this._group.hide();
-    global.stage.add_actor(this._group);
-    let icontheme = Gtk.IconTheme.get_default();
-    let rect = new Clutter.Rectangle({ color: SIDESHOW_SEARCH_BG_COLOR,
-        x: SIDESHOW_PAD,
-        y: Panel.PANEL_HEIGHT + SIDESHOW_PAD,
-        width: width,
-        height: 24});
-    this._group.add_actor(rect);
-
-    let searchIconTexture = new Clutter.Texture({ x: SIDESHOW_PAD + 2,
-        y: rect.y + 2 });
-    let searchIconPath = icontheme.lookup_icon('gtk-find', 16, 0).get_filename();
-    searchIconTexture.set_from_file(searchIconPath);
-    this._group.add_actor(searchIconTexture);
-
-    this._searchEntry = new Clutter.Entry({
-        font_name: "Sans 14px",
-        x: searchIconTexture.x
-        + searchIconTexture.width + 4,
-        y: searchIconTexture.y,
-        width: rect.width - (searchIconTexture.x),
-        height: searchIconTexture.height});
-    this._group.add_actor(this._searchEntry);
-    global.stage.set_key_focus(this._searchEntry);
-    this._searchQueued = false;
-    this._searchActive = false;
-    this._searchEntry.connect('notify::text', function (se, prop) {           
-        if (me._searchQueued)
-            return;
-        Mainloop.timeout_add(250, function() {
-            let text = me._searchEntry.text;            
-            me._searchQueued = false;
-            me._searchActive = text != '';              
-            me._appdisplay.setSearch(text);
-            return false;
+        let global = Shell.Global.get();
+        this._group = new Clutter.Group();
+        this._group.hide();
+        global.stage.add_actor(this._group);
+        let icontheme = Gtk.IconTheme.get_default();
+        let rect = new Clutter.Rectangle({ color: SIDESHOW_SEARCH_BG_COLOR,
+                                             x: SIDESHOW_PAD,
+                                             y: Panel.PANEL_HEIGHT + SIDESHOW_PAD,
+                                             width: width,
+                                             height: 24});
+        this._group.add_actor(rect);
+
+        let searchIconTexture = new Clutter.Texture({ x: SIDESHOW_PAD + 2,
+                                                      y: rect.y + 2 });
+        let searchIconPath = icontheme.lookup_icon('gtk-find', 16, 0).get_filename();
+        searchIconTexture.set_from_file(searchIconPath);
+        this._group.add_actor(searchIconTexture);
+
+        this._searchEntry = new Clutter.Entry({
+                                             font_name: "Sans 14px",
+                                             x: searchIconTexture.x
+                                                 + searchIconTexture.width + 4,
+                                             y: searchIconTexture.y,
+                                             width: rect.width - (searchIconTexture.x),
+                                             height: searchIconTexture.height});
+        this._group.add_actor(this._searchEntry);
+        global.stage.set_key_focus(this._searchEntry);
+        this._searchQueued = false;
+        this._searchActive = false;
+        this._searchEntry.connect('notify::text', function (se, prop) {
+            if (me._searchQueued)
+                return;
+            Mainloop.timeout_add(250, function() {
+                let text = me._searchEntry.text;
+                me._searchQueued = false;
+                me._searchActive = text != '';
+                me._appdisplay.setSearch(text);
+                return false;
+            });
         });
-    });
-    this._searchEntry.connect('activate', function (se) {
-        if (!me._searchActive)
-            return false;
-        me._appdisplay.searchActivate();
-        return true;
-    });
-    this._searchEntry.connect('key-press-event', function (se, e) {
-        let code = e.get_code();
-        log("code: " + code);
-        if (code == 111) {
-            me._appdisplay.selectUp();
+        this._searchEntry.connect('activate', function (se) {
+            if (!me._searchActive)
+                return false;
+            me._appdisplay.searchActivate();
             return true;
-        } else if (code == 116) {
-            me._appdisplay.selectDown();
-            return true;
-        }
-        return false;
-    });
+        });
+        this._searchEntry.connect('key-press-event', function (se, e) {
+            let code = e.get_code();
+            log("code: " + code);
+            if (code == 111) {
+                me._appdisplay.selectUp();
+                return true;
+            } else if (code == 116) {
+                me._appdisplay.selectDown();
+                return true;
+            }
+            return false;
+        });
 
-    let appsText = new Clutter.Label({ color: SIDESHOW_TEXT_COLOR,
-        font_name: "Sans Bold 14px",
-        text: "Applications",
-        x: SIDESHOW_PAD,
-        y: this._searchEntry.y + this._searchEntry.height + 10,
-        height: 16});
-    this._group.add_actor(appsText);
-
-    let menuY = appsText.y + appsText.height + 6;
-    this._appdisplay = new AppDisplay.AppDisplay(SIDESHOW_PAD,
-            menuY, width, global.screen_height - menuY);
-
-    /* Proxy the activated signal */
-    this._appdisplay.connect('activated', function(appdisplay) {
-        me.emit('activated');
-    });
-},
-
-show: function() {
-    this._group.show();
-    this._appdisplay.show();
-},
-
-hide: function() {
-    this._group.hide();
-    this._appdisplay.hide();
-}
+        let appsText = new Clutter.Label({ color: SIDESHOW_TEXT_COLOR,
+                                           font_name: "Sans Bold 14px",
+                                           text: "Applications",
+                                           x: SIDESHOW_PAD,
+                                           y: this._searchEntry.y + this._searchEntry.height + 10,
+                                           height: 16});
+        this._group.add_actor(appsText);
+
+        let menuY = appsText.y + appsText.height + 6;
+        this._appdisplay = new AppDisplay.AppDisplay(SIDESHOW_PAD,
+                menuY, width, global.screen_height - menuY);
+
+        /* Proxy the activated signal */
+        this._appdisplay.connect('activated', function(appdisplay) {
+          me.emit('activated');
+        });
+    },
+
+    show: function() {
+          this._group.show();
+          this._appdisplay.show();
+    },
+
+    hide: function() {
+          this._group.hide();
+          this._appdisplay.hide();
+    }
 };
 Signals.addSignalMethods(Sideshow.prototype);
 
@@ -148,252 +148,254 @@
 }
 
 Overlay.prototype = {
-_init : function() {
-    let me = this;
+    _init : function() {
+        let me = this;
 
-    let global = Shell.Global.get();
+        let global = Shell.Global.get();
 
-    this._group = new Clutter.Group();
-    this.visible = false;
+        this._group = new Clutter.Group();
+        this.visible = false;
 
-    let background = new Clutter.Rectangle({ color: OVERLAY_BACKGROUND_COLOR,
-        reactive: true,
-        x: 0,
-        y: Panel.PANEL_HEIGHT,
-        width: global.screen_width,
-        height: global.screen_width - Panel.PANEL_HEIGHT });
-    this._group.add_actor(background);
+        let background = new Clutter.Rectangle({ color: OVERLAY_BACKGROUND_COLOR,
+                                                 reactive: true,
+                                                 x: 0,
+                                                 y: Panel.PANEL_HEIGHT,
+                                                 width: global.screen_width,
+                                                 height: global.screen_width - Panel.PANEL_HEIGHT });
+        this._group.add_actor(background);
 
-    this._group.hide();
-    global.overlay_group.add_actor(this._group);
+        this._group.hide();
+        global.overlay_group.add_actor(this._group);
 
     this._windowClones = [];
 
-    // TODO - recalculate everything when desktop size changes
-    this._recalculateSize();
+        // TODO - recalculate everything when desktop size changes
+        this._recalculateSize();
 
-    this._sideshow = new Sideshow(this._desktopX - 10);
-    this._sideshow.connect('activated', function(sideshow) {
-        // TODO - have some sort of animation/effect while
-        // transitioning to the new app.  We definitely need
-        // startup-notification integration at least.
-        me._deactivate();
-    });
-},
-
-_recalculateSize: function () {
-    let global = Shell.Global.get();
-    let screenWidth = global.screen_width;
-    let screenHeight = global.screen_height;
-    // The desktop windows are shown on top of a scaled down version of the
-    // desktop. This is positioned at the right side of the screen
-    this._desktopWidth = screenWidth * DESKTOP_SCALE;
-    this._desktopHeight = screenHeight * DESKTOP_SCALE;
-    this._desktopX = screenWidth - this._desktopWidth - 10;
-    this._desktopY = Panel.PANEL_HEIGHT + (screenHeight - this._desktopHeight - Panel.PANEL_HEIGHT) / 2;
-},
-
-show : function() {
-    if (this.visible)
-        return;
-    this.visible = true;
-
-    let global = Shell.Global.get();
-
-    let windows = global.get_windows();
-    let desktopWindow = null;
-
-    this._recalculateSize();
-
-    for (let i = 0; i < windows.length; i++)
-        if (windows[i].get_window_type() == Meta.WindowType.DESKTOP)
-            desktopWindow = windows[i];
-
-    // If a file manager is displaying desktop icons, there will be a desktop window.
-    // This window will have the size of the whole desktop. When such window is not present
-    // (e.g. when the preference for showing icons on the desktop is disabled by the user
-    // or we are running inside a Xephyr window), we should create a desktop rectangle
-    // to serve as the background.
-    if (desktopWindow)
-        this._createDesktopClone(desktopWindow);
-    else
-        this._createDesktopRectangle();
-
-    // Count the total number of windows so we know what layout scheme to use
-    let numberOfWindows = 0;
-    for (let i = 0; i < windows.length; i++) {
-        let w = windows[i];
-        if (w == desktopWindow || w.is_override_redirect())
-            continue;
+        this._sideshow = new Sideshow(this._desktopX - 10);
+        this._sideshow.connect('activated', function(sideshow) {
+            // TODO - have some sort of animation/effect while
+            // transitioning to the new app.  We definitely need
+            // startup-notification integration at least.
+            me._deactivate();
+        });
+    },
 
-        numberOfWindows++;
-    }
+    _recalculateSize: function () {
+        let global = Shell.Global.get();
+        let screenWidth = global.screen_width;
+        let screenHeight = global.screen_height;
+        // The desktop windows are shown on top of a scaled down version of the
+        // desktop. This is positioned at the right side of the screen
+        this._desktopWidth = screenWidth * DESKTOP_SCALE;
+        this._desktopHeight = screenHeight * DESKTOP_SCALE;
+        this._desktopX = screenWidth - this._desktopWidth - 10;
+        this._desktopY = Panel.PANEL_HEIGHT + (screenHeight - this._desktopHeight - Panel.PANEL_HEIGHT) / 2;
+    },
 
-    // Now create actors for all the desktop windows. Do it in
-    // reverse order so that the active actor ends up on top
-    let windowIndex = 0;
-    for (let i = windows.length - 1; i >= 0; i--) {
-        let w = windows[i];
-        if (w == desktopWindow || w.is_override_redirect())
-            continue;
-        this._createWindowClone(w, numberOfWindows - windowIndex - 1, numberOfWindows);
+    show : function() {
+        if (this.visible)
+            return;
 
-        windowIndex++;
-    }
+        this.visible = true;
 
-    this._sideshow.show();
+        let global = Shell.Global.get();
 
-    // All the the actors in the window group are completely obscured,
-    // hiding the group holding them while the overlay is displayed greatly
-    // increases performance of the overlay especially when there are many
-    // windows visible.
-    //
-    // If we switched to displaying the actors in the overlay rather than
-    // clones of them, this would obviously no longer be necessary.
-    global.window_group.hide()
-    this._group.show();
-},
-
-hide : function() {
-    if (!this.visible)
-        return;
-    let global = Shell.Global.get();
-
-    this.visible = false;
-    global.window_group.show()
-    this._group.hide();
+        let windows = global.get_windows();
+        let desktopWindow = null;
 
-    for (let i = 0; i < this._windowClones.length; i++) {
-        this._windowClones[i].destroy();
-    }
+        this._recalculateSize();
 
-    this._sideshow.hide();
+        for (let i = 0; i < windows.length; i++)
+            if (windows[i].get_window_type() == Meta.WindowType.DESKTOP)
+                desktopWindow = windows[i];
+
+        // If a file manager is displaying desktop icons, there will be a desktop window.
+        // This window will have the size of the whole desktop. When such window is not present
+        // (e.g. when the preference for showing icons on the desktop is disabled by the user
+        // or we are running inside a Xephyr window), we should create a desktop rectangle
+        // to serve as the background.
+        if (desktopWindow)
+            this._createDesktopClone(desktopWindow);
+        else
+            this._createDesktopRectangle();
+
+        // Count the total number of windows so we know what layout scheme to use
+        let numberOfWindows = 0;
+        for (let i = 0; i < windows.length; i++) {
+            let w = windows[i];
+            if (w == desktopWindow || w.is_override_redirect())
+                continue;
 
-    this._windowClones = [];
-},
+            numberOfWindows++;
+        }
 
-_createDesktopClone : function(w) {
-    let clone = new Clutter.CloneTexture({ parent_texture: w.get_texture(),
-        reactive: true,
-        x: 0,
-        y: 0 });
-    this._addDesktop(clone);
-},
-
-_createDesktopRectangle : function() {
-    let global = Shell.Global.get();
-    // In the case when we have a desktop window from the file manager, its height is
-    // full-screen, i.e. it includes the height of the panel, so we should not subtract
-    // the height of the panel from global.screen_height here either to have them show
-    // up identically.
-    // We are also using (0,0) coordinates in both cases which makes the background
-    // window animate out from behind the panel.
-    let desktopRectangle = new Clutter.Rectangle({ color: global.stage.color,
-        reactive: true,
-        x: 0,
-        y: 0,
-        width: global.screen_width,
-        height: global.screen_height });
-    this._addDesktop(desktopRectangle);
-},
-
-_addDesktop : function(desktop) {
-    let me = this;
-
-    this._windowClones.push(desktop);
-    this._group.add_actor(desktop);
-
-    // Since the right side only moves a little bit (the width of padding
-    // we add) it looks less jittery to put the anchor there.
-    desktop.move_anchor_point_from_gravity(Clutter.Gravity.NORTH_EAST);
-    Tweener.addTween(desktop,
-            { x: this._desktopX + this._desktopWidth,
-        y: this._desktopY,
-        scale_x: DESKTOP_SCALE,
-        scale_y: DESKTOP_SCALE,
-        time: ANIMATION_TIME,
-        transition: "easeOutQuad"
-            });
+        // Now create actors for all the desktop windows. Do it in
+        // reverse order so that the active actor ends up on top
+        let windowIndex = 0;
+        for (let i = windows.length - 1; i >= 0; i--) {
+            let w = windows[i];
+            if (w == desktopWindow || w.is_override_redirect())
+                continue;
+            this._createWindowClone(w, numberOfWindows - windowIndex - 1, numberOfWindows);
 
-    desktop.connect("button-press-event",
-            function() {
-        me._deactivate();
-    });
-},
-
-//windowIndex == 0 => top in stacking order
-_computeWindowPosition : function(windowIndex, numberOfWindows) {
-    if (numberOfWindows in POSITIONS)
-        return POSITIONS[numberOfWindows][windowIndex];
-
-    // If we don't have a predefined scheme for this window count, overlap the windows
-    // along the diagonal of the desktop (improve this!)
-    let fraction = Math.sqrt(1/numberOfWindows);
-
-    // The top window goes at the lower right - this is different from the
-    // fixed position schemes where the windows are in "reading order"
-    // and the top window goes at the upper left.
-    let pos = (numberOfWindows - windowIndex - 1) / (numberOfWindows - 1);
-    let xCenter = (fraction / 2) + (1 - fraction) * pos;
-    let yCenter = xCenter;
-
-    return [xCenter, yCenter, fraction];
-},
-
-_createWindowClone : function(w, windowIndex, numberOfWindows) {
-    let me = this;
-
-    // We show the window using "clones" of the texture .. separate
-    // actors that mirror the original actors for the window. For
-    // animation purposes, it may be better to actually move the
-    // original actors about instead.
-
-    let clone = new Clutter.CloneTexture({ parent_texture: w.get_texture(),
-        reactive: true,
-        x: w.x,
-        y: w.y });
-
-    let [xCenter, yCenter, fraction] = this._computeWindowPosition(windowIndex, numberOfWindows);
-
-    let desiredSize = this._desktopWidth * fraction;
-
-    xCenter = this._desktopX + xCenter * this._desktopWidth;
-    yCenter = this._desktopY + yCenter * this._desktopHeight;
-
-    let size = clone.width;
-    if (clone.height > size)
-        size = clone.height;
-
-    // Never scale up
-    let scale = desiredSize / size;
-    if (scale > 1)
-        scale = 1;
-
-    this._group.add_actor(clone);
-    this._windowClones.push(clone);
-
-    Tweener.addTween(clone,
-            { x: xCenter - 0.5 * scale * w.width,
-        y: yCenter - 0.5 * scale * w.height,
-        scale_x: scale,
-        scale_y: scale,
-        time: ANIMATION_TIME,
-        opacity: WINDOW_OPACITY,
-        transition: "easeOutQuad"
-            });
+            windowIndex++;
+        }
 
-    clone.connect("button-press-event",
-            function(clone, event) {
-        me._activateWindow(w, event.get_time());
-    });
-},
-
-_activateWindow : function(w, time) {
-    this._deactivate();
-    w.get_meta_window().activate(time);
-},
+        this._sideshow.show();
 
-_deactivate : function() {
-    Main.hide_overlay();
-}
+        // All the the actors in the window group are completely obscured,
+        // hiding the group holding them while the overlay is displayed greatly
+        // increases performance of the overlay especially when there are many
+        // windows visible.
+        //
+        // If we switched to displaying the actors in the overlay rather than
+        // clones of them, this would obviously no longer be necessary.
+        global.window_group.hide()
+        this._group.show();
+    },
+
+    hide : function() {
+        if (!this.visible)
+            return;
+
+        let global = Shell.Global.get();
+
+        this.visible = false;
+        global.window_group.show()
+        this._group.hide();
+
+        for (let i = 0; i < this._windowClones.length; i++) {
+            this._windowClones[i].destroy();
+        }
+
+        this._sideshow.hide();
+
+        this._windowClones = [];
+    },
+
+    _createDesktopClone : function(w) {
+        let clone = new Clutter.CloneTexture({ parent_texture: w.get_texture(),
+                                               reactive: true,
+                                               x: 0,
+                                               y: 0 });
+        this._addDesktop(clone);
+    },
+
+    _createDesktopRectangle : function() {
+        let global = Shell.Global.get();
+        // In the case when we have a desktop window from the file manager, its height is
+        // full-screen, i.e. it includes the height of the panel, so we should not subtract
+        // the height of the panel from global.screen_height here either to have them show
+        // up identically.
+        // We are also using (0,0) coordinates in both cases which makes the background
+        // window animate out from behind the panel.
+        let desktopRectangle = new Clutter.Rectangle({ color: global.stage.color,
+                                                        reactive: true,
+                                                        x: 0,
+                                                        y: 0,
+                                                        width: global.screen_width,
+                                                        height: global.screen_height });
+        this._addDesktop(desktopRectangle);
+    },
+
+    _addDesktop : function(desktop) {
+        let me = this;
+
+        this._windowClones.push(desktop);
+        this._group.add_actor(desktop);
+
+        // Since the right side only moves a little bit (the width of padding
+        // we add) it looks less jittery to put the anchor there.
+        desktop.move_anchor_point_from_gravity(Clutter.Gravity.NORTH_EAST);
+        Tweener.addTween(desktop,
+                         { x: this._desktopX + this._desktopWidth,
+                           y: this._desktopY,
+                           scale_x: DESKTOP_SCALE,
+                           scale_y: DESKTOP_SCALE,
+                           time: ANIMATION_TIME,
+                           transition: "easeOutQuad"
+                         });
+
+        desktop.connect("button-press-event",
+                      function() {
+                          me._deactivate();
+                      });
+    },
+
+    // windowIndex == 0 => top in stacking order
+    _computeWindowPosition : function(windowIndex, numberOfWindows) {
+        if (numberOfWindows in POSITIONS)
+            return POSITIONS[numberOfWindows][windowIndex];
+
+        // If we don't have a predefined scheme for this window count, overlap the windows
+        // along the diagonal of the desktop (improve this!)
+        let fraction = Math.sqrt(1/numberOfWindows);
+
+        // The top window goes at the lower right - this is different from the
+        // fixed position schemes where the windows are in "reading order"
+        // and the top window goes at the upper left.
+        let pos = (numberOfWindows - windowIndex - 1) / (numberOfWindows - 1);
+        let xCenter = (fraction / 2) + (1 - fraction) * pos;
+        let yCenter = xCenter;
+
+        return [xCenter, yCenter, fraction];
+    },
+
+    _createWindowClone : function(w, windowIndex, numberOfWindows) {
+        let me = this;
+
+        // We show the window using "clones" of the texture .. separate
+        // actors that mirror the original actors for the window. For
+        // animation purposes, it may be better to actually move the
+        // original actors about instead.
+
+        let clone = new Clutter.CloneTexture({ parent_texture: w.get_texture(),
+                                               reactive: true,
+                                               x: w.x,
+                                               y: w.y });
+
+        let [xCenter, yCenter, fraction] = this._computeWindowPosition(windowIndex, numberOfWindows);
+
+        let desiredSize = this._desktopWidth * fraction;
+
+        xCenter = this._desktopX + xCenter * this._desktopWidth;
+        yCenter = this._desktopY + yCenter * this._desktopHeight;
+
+        let size = clone.width;
+        if (clone.height > size)
+            size = clone.height;
+
+        // Never scale up
+        let scale = desiredSize / size;
+        if (scale > 1)
+            scale = 1;
+
+        this._group.add_actor(clone);
+        this._windowClones.push(clone);
+
+        Tweener.addTween(clone,
+                         { x: xCenter - 0.5 * scale * w.width,
+                           y: yCenter - 0.5 * scale * w.height,
+                           scale_x: scale,
+                           scale_y: scale,
+                           time: ANIMATION_TIME,
+                           opacity: WINDOW_OPACITY,
+                           transition: "easeOutQuad"
+                          });
+
+        clone.connect("button-press-event",
+                      function(clone, event) {
+                          me._activateWindow(w, event.get_time());
+                      });
+    },
+
+    _activateWindow : function(w, time) {
+        this._deactivate();
+        w.get_meta_window().activate(time);
+    },
+
+    _deactivate : function() {
+        Main.hide_overlay();
+    }
 };

Modified: trunk/js/ui/panel.js
==============================================================================
--- trunk/js/ui/panel.js	(original)
+++ trunk/js/ui/panel.js	Mon Dec  1 19:51:43 2008
@@ -1,4 +1,4 @@
-/* -*- mode: js2; js2-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil -*- */
+/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 
 const Clutter = imports.gi.Clutter;
 const Mainloop = imports.mainloop;
@@ -21,123 +21,123 @@
 }
 
 Panel.prototype = {
-_init : function() {
-    let global = Shell.Global.get();
+    _init : function() {
+        let global = Shell.Global.get();
 
-    this._group = new Clutter.Group();
+        this._group = new Clutter.Group();
 
-    let background = new Clutter.Rectangle({ color: PANEL_BACKGROUND_COLOR,
-        reactive: true,
-        width: global.screen_width+2,
-        height: PANEL_HEIGHT+1,
-        border_width: 1});
-    background.set_position(-1, -1);
-    this._group.add_actor(background);
-
-    this.button = new Button.Button("Activities", PANEL_BACKGROUND_COLOR, PRESSED_BUTTON_BACKGROUND_COLOR, true, null, PANEL_HEIGHT-1);
-
-    this._group.add_actor(this.button.button);
-
-    this._grid = new Tidy.Grid({ height: TRAY_HEIGHT,
-        valign: 0.5,
-        end_align: true,
-        column_gap: 2 })
-    this._group.add_actor(this._grid);
-
-    this._clock = new Clutter.Label({ font_name: "Sans Bold 16px",
-        text: "" });
-    this._grid.add_actor(this._clock);
-
-    // Setting the anchor point at top right (north east) makes that portion of the
-    // grid positioned at the position specified below.
-    this._grid.set_anchor_point_from_gravity(Clutter.Gravity.NORTH_EAST);
-    this._grid.set_position(global.screen_width - 2, (PANEL_HEIGHT - TRAY_HEIGHT) / 2);
-
-    this._traymanager = new Shell.TrayManager({ bg_color: PANEL_BACKGROUND_COLOR });
-    let me = this;
-    // the anchor point needs to be updated each time the height/width of the content might have changed, because
-    // it doesn't get updated on its own
-    this._traymanager.connect('tray-icon-added',
+        let background = new Clutter.Rectangle({ color: PANEL_BACKGROUND_COLOR,
+                                                 reactive: true,
+                                                 width: global.screen_width+2,
+                                                 height: PANEL_HEIGHT+1,
+                                                 border_width: 1});
+        background.set_position(-1, -1);
+        this._group.add_actor(background);
+
+        this.button = new Button.Button("Activities", PANEL_BACKGROUND_COLOR, PRESSED_BUTTON_BACKGROUND_COLOR, true, null, PANEL_HEIGHT-1);
+
+        this._group.add_actor(this.button.button);
+
+        this._grid = new Tidy.Grid({ height: TRAY_HEIGHT,
+                                     valign: 0.5,
+                                     end_align: true,
+                                     column_gap: 2 })
+        this._group.add_actor(this._grid);
+
+        this._clock = new Clutter.Label({ font_name: "Sans Bold 16px",
+                                          text: "" });
+        this._grid.add_actor(this._clock);
+
+        // Setting the anchor point at top right (north east) makes that portion of the
+        // grid positioned at the position specified below.
+        this._grid.set_anchor_point_from_gravity(Clutter.Gravity.NORTH_EAST);
+        this._grid.set_position(global.screen_width - 2, (PANEL_HEIGHT - TRAY_HEIGHT) / 2);
+
+        this._traymanager = new Shell.TrayManager({ bg_color: PANEL_BACKGROUND_COLOR });
+        let me = this;
+        // the anchor point needs to be updated each time the height/width of the content might have changed, because
+        // it doesn't get updated on its own
+        this._traymanager.connect('tray-icon-added',
             function(o, icon) {
-        me._grid.add_actor(icon);
-        /* bump the clock back to the end */
-        me._grid.remove_actor(me._clock);
-        me._grid.add_actor(me._clock);
-        me._grid.move_anchor_point_from_gravity(Clutter.Gravity.NORTH_EAST);
-    });
-    this._traymanager.connect('tray-icon-removed',
+                me._grid.add_actor(icon);
+                /* bump the clock back to the end */
+                me._grid.remove_actor(me._clock);
+                me._grid.add_actor(me._clock);
+                me._grid.move_anchor_point_from_gravity(Clutter.Gravity.NORTH_EAST);
+            });
+        this._traymanager.connect('tray-icon-removed',
             function(o, icon) {
-        me._grid.remove_actor(icon);
-        me._grid.move_anchor_point_from_gravity(Clutter.Gravity.NORTH_EAST);
-    });
-    this._traymanager.manage_stage(global.stage);
-
-    // TODO: decide what to do with the rest of the panel in the overlay mode (make it fade-out, become non-reactive, etc.)
-    // We get into the overlay mode on button-press-event as opposed to button-release-event because eventually we'll probably
-    // have the overlay act like a menu that allows the user to release the mouse on the activity the user wants
-    // to switch to.
-    this.button.button.connect('button-press-event',
+                me._grid.remove_actor(icon);
+                me._grid.move_anchor_point_from_gravity(Clutter.Gravity.NORTH_EAST);
+            });
+        this._traymanager.manage_stage(global.stage);
+
+        // TODO: decide what to do with the rest of the panel in the overlay mode (make it fade-out, become non-reactive, etc.)
+        // We get into the overlay mode on button-press-event as opposed to button-release-event because eventually we'll probably
+        // have the overlay act like a menu that allows the user to release the mouse on the activity the user wants
+        // to switch to.
+        this.button.button.connect('button-press-event',
             function(o, event) {
-        if (Main.overlay.visible)
-            Main.hide_overlay();
-        else
-            Main.show_overlay();
+                if (Main.overlay.visible)
+                    Main.hide_overlay();
+                else
+                    Main.show_overlay();
 
-        return true;
-    });
+                return true;
+            });
 
-    this._setStruts();
-    global.screen.connect('notify::n-workspaces',
+        this._setStruts();
+        global.screen.connect('notify::n-workspaces',
             function() {
-        me._setStruts();
-    });
-
-    global.stage.add_actor(this._group);
+                me._setStruts();
+            });
 
-    this._updateClock();
-    this._startClock();
-},
-
-// Struts determine the area along each side of the screen that is reserved
-// and not available to applications
-_setStruts: function() {
-    let global = Shell.Global.get();
-
-    let struts = [
-                  new Meta.Strut({
-                      rect: {
-                      x: 0,
-                      y: 0,
-                      width: global.screen_width,
-                      height: PANEL_HEIGHT
-                  },
-                  side: Meta.Direction.TOP
-                  })
-                  ];
-
-    let screen = global.screen;
-    for (let i = 0; i < screen.n_workspaces; i++) {
-        let workspace = screen.get_workspace_by_index(i);
-        workspace.set_builtin_struts(struts);
-    }
-},
+        global.stage.add_actor(this._group);
 
-_startClock: function() {
-    let me = this;
-    // TODO: this makes the clock updated every 60 seconds, but not necessarily on the minute, so it is inaccurate
-    Mainloop.timeout_add_seconds(60,
+        this._updateClock();
+        this._startClock();
+    },
+
+    // Struts determine the area along each side of the screen that is reserved
+    // and not available to applications
+    _setStruts: function() {
+        let global = Shell.Global.get();
+
+        let struts = [
+            new Meta.Strut({
+                rect: {
+                    x: 0,
+                    y: 0,
+                    width: global.screen_width,
+                    height: PANEL_HEIGHT
+                },
+                side: Meta.Direction.TOP
+            })
+        ];
+
+        let screen = global.screen;
+        for (let i = 0; i < screen.n_workspaces; i++) {
+            let workspace = screen.get_workspace_by_index(i);
+            workspace.set_builtin_struts(struts);
+        }
+    },
+
+    _startClock: function() {
+        let me = this;
+        // TODO: this makes the clock updated every 60 seconds, but not necessarily on the minute, so it is inaccurate
+        Mainloop.timeout_add_seconds(60,
             function() {
-        me._updateClock();
-        return true;
-    });
-},
+                me._updateClock();
+                return true;
+            });
+    },
 
-_updateClock: function() {
-    this._clock.set_text(new Date().toLocaleFormat("%H:%M"));
-    return true;
-},
+    _updateClock: function() {
+        this._clock.set_text(new Date().toLocaleFormat("%H:%M"));
+        return true;
+    },
 
-overlayHidden: function() {
-    this.button.release();
-}
+    overlayHidden: function() {
+        this.button.release();
+    }
 };

Modified: trunk/js/ui/run_dialog.js
==============================================================================
--- trunk/js/ui/run_dialog.js	(original)
+++ trunk/js/ui/run_dialog.js	Mon Dec  1 19:51:43 2008
@@ -1,4 +1,4 @@
-/* -*- mode: js2; js2-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil -*- */
+/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 
 const Signals = imports.signals;
 const Shell = imports.gi.Shell;
@@ -23,110 +23,111 @@
 };
 
 RunDialog.prototype = {
-        _init : function() {
-    let global = Shell.Global.get();
+    _init : function() {
+        let global = Shell.Global.get();
 
-    // All actors are inside _group. We create it initially
-    // hidden then show it in show()
-    this._group = new Clutter.Group({ visible: false });
-    global.stage.add_actor(this._group);
-
-    this._overlay = new Clutter.Rectangle({ color: OVERLAY_COLOR,
-        width: global.screen_width,
-        height: global.screen_height,
-        border_width: 0,
-        reactive: true });
-    this._group.add_actor(this._overlay);
-
-    let boxGroup = new Clutter.Group();
-    boxGroup.set_position((global.screen_width - BOX_WIDTH) / 2,
-            (global.screen_height - BOX_HEIGHT) / 2);
-    this._group.add_actor(boxGroup);
-
-    let box = new Clutter.Rectangle({ color: BOX_BACKGROUND_COLOR,
-        reactive: false,
-        width: BOX_WIDTH,
-        height: BOX_HEIGHT,
-        border_width: 0 });
-    boxGroup.add_actor(box);
-
-    let label = new Clutter.Label({ color: BOX_TEXT_COLOR,
-        font_name: '18px Sans',
-        text: 'Please enter a command:' });
-    label.set_position(6, 6);
-    boxGroup.add_actor(label);
-
-    this._entry = new Clutter.Entry({ color: BOX_TEXT_COLOR,
-        font_name: '20px Sans Bold',
-        reactive: true,
-        text: '',
-        entry_padding: 0,
-        width: BOX_WIDTH - 12,
-        height: BOX_HEIGHT - 12 });
-    // TODO: Implement relative positioning using Tidy.
-    this._entry.set_position(6, 30);
-    boxGroup.add_actor(this._entry);
-
-    let me = this;
-
-    this._entry.connect('activate', function (o, e) {
-        me.hide();
-        me._run(o.get_text());
-        return false;
-    });
-
-},
-
-_run : function(command) {
-    if (command) {
-        var p = new Shell.Process({'args' : [command]});
-        try {
-            p.run();
-        } catch (e) {
-            // TODO: Give the user direct feedback.
-            log('Could not run command ' + command + '.');
-        }
-    }
+        // All actors are inside _group. We create it initially
+        // hidden then show it in show()
+        this._group = new Clutter.Group({ visible: false });
+        global.stage.add_actor(this._group);
+
+        this._overlay = new Clutter.Rectangle({ color: OVERLAY_COLOR,
+                                                width: global.screen_width,
+                                                height: global.screen_height,
+                                                border_width: 0,
+                                                reactive: true });
+        this._group.add_actor(this._overlay);
+
+        let boxGroup = new Clutter.Group();
+        boxGroup.set_position((global.screen_width - BOX_WIDTH) / 2,
+                              (global.screen_height - BOX_HEIGHT) / 2);
+        this._group.add_actor(boxGroup);
+
+        let box = new Clutter.Rectangle({ color: BOX_BACKGROUND_COLOR,
+                                          reactive: false,
+                                          width: BOX_WIDTH,
+                                          height: BOX_HEIGHT,
+                                          border_width: 0 });
+        boxGroup.add_actor(box);
+
+        let label = new Clutter.Label({ color: BOX_TEXT_COLOR,
+                                        font_name: '18px Sans',
+                                        text: 'Please enter a command:' });
+        label.set_position(6, 6);
+        boxGroup.add_actor(label);
+
+        this._entry = new Clutter.Entry({ color: BOX_TEXT_COLOR,
+                                          font_name: '20px Sans Bold',
+                                          reactive: true,
+                                          text: '',
+                                          entry_padding: 0,
+                                          width: BOX_WIDTH - 12,
+                                          height: BOX_HEIGHT - 12 });
+        // TODO: Implement relative positioning using Tidy.
+        this._entry.set_position(6, 30);
+        boxGroup.add_actor(this._entry);
+
+        let me = this;
+
+        this._entry.connect('activate', function (o, e) {
+            me.hide();
+            me._run(o.get_text());
+            return false;
+        });
 
-    this.emit('run');
-},
+    },
 
-show : function() {
-    let me = this;
-    if (this._group.visible) // Already shown
-        return false;
+    _run : function(command) {
+        if (command) {
+            var p = new Shell.Process({'args' : [command]});
+            try {
+                p.run();
+            } catch (e) {
+                // TODO: Give the user direct feedback.
+                log('Could not run command ' + command + '.');
+            }
+        }
 
-    if (!Main.startModal())
-        return false;
+        this.emit('run');
+    },
 
-    this._group.show_all();
+    show : function() {
+        let me = this;
 
-    this._entry.connect('key-press-event', function(o, e) {
-        if (e.get_code() == 9) {
-            me.hide();
-            me.emit('cancel');
-            return true;
-        } else
+        if (this._group.visible) // Already shown
             return false;
-    });
 
-    let global = Shell.Global.get();
-    global.stage.set_key_focus(this._entry);
+        if (!Main.startModal())
+            return false;
 
-    return true;
-},
+        this._group.show_all();
 
-hide : function() {
-    if (!this._group.visible)
-        return;
-
-    this._group.hide();
-    Main.endModal();
-},
-
-destroy : function(){
-    this.hide();
-    this._group.destroy();
-}
+        this._entry.connect('key-press-event', function(o, e) {
+            if (e.get_code() == 9) {
+                me.hide();
+                me.emit('cancel');
+                return true;
+            } else
+                return false;
+        });
+
+        let global = Shell.Global.get();
+        global.stage.set_key_focus(this._entry);
+
+        return true;
+    },
+
+    hide : function() {
+        if (!this._group.visible)
+            return;
+
+        this._group.hide();
+        Main.endModal();
+    },
+
+    destroy : function(){
+        this.hide();
+        this._group.destroy();
+    }
 };
 Signals.addSignalMethods(RunDialog.prototype);

Modified: trunk/js/ui/windowmanager.js
==============================================================================
--- trunk/js/ui/windowmanager.js	(original)
+++ trunk/js/ui/windowmanager.js	Mon Dec  1 19:51:43 2008
@@ -1,4 +1,4 @@
-/* -*- mode: js2; js2-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil -*- */
+/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 
 const Clutter = imports.gi.Clutter;
 const Mainloop = imports.mainloop;
@@ -15,111 +15,111 @@
 }
 
 WindowManager.prototype = {
-_init : function() {
-    let me = this;
+    _init : function() {
+        let me = this;
 
-    this._global = Shell.Global.get();
-    this._shellwm = this._global.window_manager;
+        this._global = Shell.Global.get();
+        this._shellwm = this._global.window_manager;
 
-    this._switchData = null;
-    this._shellwm.connect('switch-workspace',
+        this._switchData = null;
+        this._shellwm.connect('switch-workspace',
             function(o, from, to, direction) {
-        let actors = me._shellwm.get_switch_workspace_actors();
-        me.switchWorkspace(actors, from, to, direction);
-    });
-    this._shellwm.connect('kill-switch-workspace',
+                let actors = me._shellwm.get_switch_workspace_actors();
+                me.switchWorkspace(actors, from, to, direction);
+            });
+        this._shellwm.connect('kill-switch-workspace',
             function(o) {
-        me.switchWorkspaceDone();
-    });
-},
-
-switchWorkspace : function(windows, from, to, direction) {
-    /* @direction is the direction that the "camera" moves, so the
-     * screen contents have to move one screen's worth in the
-     * opposite direction.
-     */
-    let xDest = 0, yDest = 0;
+                me.switchWorkspaceDone();
+            });
+    },
+
+    switchWorkspace : function(windows, from, to, direction) {
+        /* @direction is the direction that the "camera" moves, so the
+         * screen contents have to move one screen's worth in the
+         * opposite direction.
+         */
+        let xDest = 0, yDest = 0;
 
-    if (direction == Meta.MotionDirection.UP ||
+        if (direction == Meta.MotionDirection.UP ||
             direction == Meta.MotionDirection.UP_LEFT ||
             direction == Meta.MotionDirection.UP_RIGHT)
-        yDest = this._global.screen_height;
-    else if (direction == Meta.MotionDirection.DOWN ||
+                yDest = this._global.screen_height;
+        else if (direction == Meta.MotionDirection.DOWN ||
             direction == Meta.MotionDirection.DOWN_LEFT ||
             direction == Meta.MotionDirection.DOWN_RIGHT)
-        yDest = -this._global.screen_height;
+                yDest = -this._global.screen_height;
 
-    if (direction == Meta.MotionDirection.LEFT ||
+        if (direction == Meta.MotionDirection.LEFT ||
             direction == Meta.MotionDirection.UP_LEFT ||
             direction == Meta.MotionDirection.DOWN_LEFT)
-        xDest = this._global.screen_width;
-    else if (direction == Meta.MotionDirection.RIGHT ||
-            direction == Meta.MotionDirection.UP_RIGHT ||
-            direction == Meta.MotionDirection.DOWN_RIGHT)
-        xDest = -this._global.screen_width;
-
-    let switchData = {};
-    this._switchData = switchData;
-    switchData.inGroup = new Clutter.Group();
-    switchData.outGroup = new Clutter.Group();
-    switchData.windows = [];
-
-    let wgroup = this._global.window_group;
-    wgroup.add_actor(switchData.inGroup);
-    wgroup.add_actor(switchData.outGroup);
-
-    for (let i = 0; i < windows.length; i++) {
-        let window = windows[i];
-        if (window.get_workspace() == from) {
-            switchData.windows.push({ window: window,
-                parent: window.get_parent() });
-            window.reparent(switchData.outGroup);
-        } else if (window.get_workspace() == to) {
-            switchData.windows.push({ window: window,
-                parent: window.get_parent() });
-            window.reparent(switchData.inGroup);
-            window.show_all();
+                xDest = this._global.screen_width;
+        else if (direction == Meta.MotionDirection.RIGHT ||
+                 direction == Meta.MotionDirection.UP_RIGHT ||
+                 direction == Meta.MotionDirection.DOWN_RIGHT)
+                xDest = -this._global.screen_width;
+
+        let switchData = {};
+        this._switchData = switchData;
+        switchData.inGroup = new Clutter.Group();
+        switchData.outGroup = new Clutter.Group();
+        switchData.windows = [];
+
+        let wgroup = this._global.window_group;
+        wgroup.add_actor(switchData.inGroup);
+        wgroup.add_actor(switchData.outGroup);
+
+        for (let i = 0; i < windows.length; i++) {
+            let window = windows[i];
+            if (window.get_workspace() == from) {
+                switchData.windows.push({ window: window,
+                                          parent: window.get_parent() });
+                window.reparent(switchData.outGroup);
+            } else if (window.get_workspace() == to) {
+                switchData.windows.push({ window: window,
+                                          parent: window.get_parent() });
+                window.reparent(switchData.inGroup);
+                window.show_all();
+            }
         }
-    }
 
-    switchData.inGroup.set_position(-xDest, -yDest);
-    switchData.inGroup.raise_top();
+        switchData.inGroup.set_position(-xDest, -yDest);
+        switchData.inGroup.raise_top();
 
-    Tweener.addTween(switchData.outGroup,
-            { x: xDest,
-        y: yDest,
-        time: SWITCH_ANIMATION_TIME,
-        transition: "easeOutBack",
-        onComplete: this.switchWorkspaceDone
-            });
-    Tweener.addTween(switchData.inGroup,
-            { x: 0,
-        y: 0,
-        time: SWITCH_ANIMATION_TIME,
-        transition: "easeOutBack"
-            });
-},
+        Tweener.addTween(switchData.outGroup,
+                         { x: xDest,
+                           y: yDest,
+                           time: SWITCH_ANIMATION_TIME,
+                           transition: "easeOutBack",
+                           onComplete: this.switchWorkspaceDone
+                         });
+        Tweener.addTween(switchData.inGroup,
+                         { x: 0,
+                           y: 0,
+                           time: SWITCH_ANIMATION_TIME,
+                           transition: "easeOutBack"
+                         });
+    },
+
+    switchWorkspaceDone : function() {
+        let switchData = this._switchData;
+        if (!switchData)
+            return;
+        this._switchData = null;
+
+        for (let i = 0; i < switchData.windows.length; i++) {
+                let w = switchData.windows[i];
+                if (w.window.get_parent() == switchData.outGroup) {
+                    w.window.reparent(w.parent);
+                    w.window.hide();
+                } else
+                    w.window.reparent(w.parent);
+        }
+        Tweener.removeTweens(switchData.inGroup);
+        Tweener.removeTweens(switchData.outGroup);
+        switchData.inGroup.destroy();
+        switchData.outGroup.destroy();
 
-switchWorkspaceDone : function() {
-    let switchData = this._switchData;
-    if (!switchData)
-        return;
-    this._switchData = null;
-
-    for (let i = 0; i < switchData.windows.length; i++) {
-        let w = switchData.windows[i];
-        if (w.window.get_parent() == switchData.outGroup) {
-            w.window.reparent(w.parent);
-            w.window.hide();
-        } else
-            w.window.reparent(w.parent);
+        this._shellwm.completed_switch_workspace();
     }
-    Tweener.removeTweens(switchData.inGroup);
-    Tweener.removeTweens(switchData.outGroup);
-    switchData.inGroup.destroy();
-    switchData.outGroup.destroy();
-
-    this._shellwm.completed_switch_workspace();
-}
 
 };



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]