[AppSwitcher] Use AppIcon and switch applications rather than windows

https://bugzilla.gnome.org/show_bug.cgi?id=590563
This commit is contained in:
Dan Winship 2009-08-13 12:52:50 -04:00
parent 11d884d724
commit 67bfbc9b4b

View File

@ -7,26 +7,19 @@ const Meta = imports.gi.Meta;
const Pango = imports.gi.Pango; const Pango = imports.gi.Pango;
const Shell = imports.gi.Shell; const Shell = imports.gi.Shell;
const AppIcon = imports.ui.appIcon;
const Lightbox = imports.ui.lightbox; const Lightbox = imports.ui.lightbox;
const Main = imports.ui.main; const Main = imports.ui.main;
const Tweener = imports.ui.tweener;
const POPUP_BG_COLOR = new Clutter.Color(); const POPUP_BG_COLOR = new Clutter.Color();
POPUP_BG_COLOR.from_pixel(0x00000080); POPUP_BG_COLOR.from_pixel(0x000000ff);
const POPUP_INDICATOR_COLOR = new Clutter.Color();
POPUP_INDICATOR_COLOR.from_pixel(0xf0f0f0ff);
const POPUP_TRANSPARENT = new Clutter.Color(); const POPUP_TRANSPARENT = new Clutter.Color();
POPUP_TRANSPARENT.from_pixel(0x00000000); POPUP_TRANSPARENT.from_pixel(0x00000000);
const POPUP_INDICATOR_WIDTH = 4;
const POPUP_GRID_SPACING = 8; const POPUP_GRID_SPACING = 8;
const POPUP_ICON_SIZE = 48; const POPUP_ICON_SIZE = 48;
const POPUP_NUM_COLUMNS = 5; const POPUP_NUM_COLUMNS = 5;
const POPUP_LABEL_MAX_WIDTH = POPUP_NUM_COLUMNS * (POPUP_ICON_SIZE + POPUP_GRID_SPACING);
const SWITCH_TIME = 0.1;
function AltTabPopup() { function AltTabPopup() {
this._init(); this._init();
} }
@ -50,48 +43,24 @@ AltTabPopup.prototype = {
gcenterbox.append(this._grid, Big.BoxPackFlags.NONE); gcenterbox.append(this._grid, Big.BoxPackFlags.NONE);
this.actor.append(gcenterbox, Big.BoxPackFlags.NONE); this.actor.append(gcenterbox, Big.BoxPackFlags.NONE);
// Selected-window label this._icons = [];
this._label = new Clutter.Text({ font_name: "Sans 16px",
ellipsize: Pango.EllipsizeMode.END });
let labelbox = new Big.Box({ background_color: POPUP_INDICATOR_COLOR,
corner_radius: POPUP_GRID_SPACING / 2,
padding: POPUP_GRID_SPACING / 2 });
labelbox.append(this._label, Big.BoxPackFlags.NONE);
let lcenterbox = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
x_align: Big.BoxAlignment.CENTER,
width: POPUP_LABEL_MAX_WIDTH + POPUP_GRID_SPACING });
lcenterbox.append(labelbox, Big.BoxPackFlags.NONE);
this.actor.append(lcenterbox, Big.BoxPackFlags.NONE);
// Indicator around selected icon
this._indicator = new Big.Rectangle({ border_width: POPUP_INDICATOR_WIDTH,
corner_radius: POPUP_INDICATOR_WIDTH / 2,
border_color: POPUP_INDICATOR_COLOR,
color: POPUP_TRANSPARENT });
this.actor.append(this._indicator, Big.BoxPackFlags.FIXED);
this._items = [];
this._haveModal = false; this._haveModal = false;
this._selected = 0;
this._highlightedWindow = null;
this._toplevels = global.window_group.get_children();
global.stage.add_actor(this.actor); global.stage.add_actor(this.actor);
}, },
_addWindow : function(win) { _addIcon : function(appIcon) {
let item = { window: win, appIcon.connect('activate', Lang.bind(this, this._appClicked));
metaWindow: win.get_meta_window() }; appIcon.connect('activate-window', Lang.bind(this, this._windowClicked));
appIcon.connect('highlight-window', Lang.bind(this, this._windowHovered));
let pixbuf = item.metaWindow.icon; // FIXME?
item.icon = new Clutter.Texture({ width: POPUP_ICON_SIZE, appIcon.actor.border = 2;
height: POPUP_ICON_SIZE,
keep_aspect_ratio: true });
Shell.clutter_texture_set_from_pixbuf(item.icon, pixbuf);
item.box = new Big.Box({ padding: POPUP_INDICATOR_WIDTH * 2 }); this._icons.push(appIcon);
item.box.append(item.icon, Big.BoxPackFlags.NONE);
item.n = this._items.length;
this._items.push(item);
// Add it to the grid // Add it to the grid
if (!this._gridRow || this._gridRow.get_children().length == POPUP_NUM_COLUMNS) { if (!this._gridRow || this._gridRow.get_children().length == POPUP_NUM_COLUMNS) {
@ -99,7 +68,7 @@ AltTabPopup.prototype = {
orientation: Big.BoxOrientation.HORIZONTAL }); orientation: Big.BoxOrientation.HORIZONTAL });
this._grid.append(this._gridRow, Big.BoxPackFlags.NONE); this._grid.append(this._gridRow, Big.BoxPackFlags.NONE);
} }
this._gridRow.append(item.box, Big.BoxPackFlags.NONE); this._gridRow.append(appIcon.actor, Big.BoxPackFlags.NONE);
}, },
show : function(initialSelection) { show : function(initialSelection) {
@ -116,17 +85,18 @@ AltTabPopup.prototype = {
this._keyPressEventId = global.stage.connect('key-press-event', Lang.bind(this, this._keyPressEvent)); this._keyPressEventId = global.stage.connect('key-press-event', Lang.bind(this, this._keyPressEvent));
this._keyReleaseEventId = global.stage.connect('key-release-event', Lang.bind(this, this._keyReleaseEvent)); this._keyReleaseEventId = global.stage.connect('key-release-event', Lang.bind(this, this._keyReleaseEvent));
// Fill in the windows // Contruct the AppIcons, sort by time, add to the popup
let windows = []; let icons = [];
for (let i = 0; i < apps.length; i++) { for (let i = 0; i < apps.length; i++)
let appWindows = appMonitor.get_windows_for_app(apps[i].get_id()); icons.push(new AppIcon.AppIcon(apps[i], AppIcon.MenuType.BELOW));
windows = windows.concat(appWindows); icons.sort(function(i1, i2) {
} // The app's most-recently-used window is first
// in its list
windows.sort(function(w1, w2) { return w2.get_user_time() - w1.get_user_time(); }); return (i2.windows[0].get_user_time() -
i1.windows[0].get_user_time());
for (let i = 0; i < windows.length; i++) });
this._addWindow(windows[i].get_compositor_private()); for (let i = 0; i < icons.length; i++)
this._addIcon(icons[i]);
// Need to specify explicit width and height because the // Need to specify explicit width and height because the
// window_group may not actually cover the whole screen // window_group may not actually cover the whole screen
@ -158,16 +128,30 @@ AltTabPopup.prototype = {
let keysym = event.get_key_symbol(); let keysym = event.get_key_symbol();
if (keysym == Clutter.Alt_L || keysym == Clutter.Alt_R) { if (keysym == Clutter.Alt_L || keysym == Clutter.Alt_R) {
if (this._selected) { if (this._highlightedWindow)
Main.activateWindow(this._selected.metaWindow, Main.activateWindow(this._highlightedWindow, event.get_time());
event.get_time());
}
this.destroy(); this.destroy();
} }
return true; return true;
}, },
_appClicked : function(icon) {
Main.activateWindow(icon.windows[0]);
this.destroy();
},
_windowClicked : function(icon, window) {
if (window)
Main.activateWindow(window);
this.destroy();
},
_windowHovered : function(icon, window) {
if (window)
this._highlightWindow(window);
},
destroy : function() { destroy : function() {
this.actor.destroy(); this.actor.destroy();
}, },
@ -186,66 +170,15 @@ AltTabPopup.prototype = {
}, },
_updateSelection : function(delta) { _updateSelection : function(delta) {
let n = ((this._selected ? this._selected.n : 0) + this._items.length + delta) % this._items.length; this._icons[this._selected].setHighlight(false);
this._selected = (this._selected + this._icons.length + delta) % this._icons.length;
this._icons[this._selected].setHighlight(true);
if (this._selected) { this._highlightWindow(this._icons[this._selected].windows[0]);
// Unselect previous
if (this._allocationChangedId) {
this._selected.box.disconnect(this._allocationChangedId);
delete this._allocationChangedId;
}
}
let item = this._items[n];
let changed = this._selected && item != this._selected;
this._selected = item;
if (this._selected) {
this._label.set_size(-1, -1);
this._label.text = this._selected.metaWindow.title;
if (this._label.width > POPUP_LABEL_MAX_WIDTH)
this._label.width = POPUP_LABEL_MAX_WIDTH;
// Figure out this._selected.box's coordinates in terms of
// this.actor
let bx = this._selected.box.x, by = this._selected.box.y;
let actor = this._selected.box.get_parent();
while (actor != this.actor) {
bx += actor.x;
by += actor.y;
actor = actor.get_parent();
}
if (changed) {
Tweener.addTween(this._indicator,
{ x: bx,
y: by,
width: this._selected.box.width,
height: this._selected.box.height,
time: SWITCH_TIME,
transition: "easeOutQuad" });
} else {
Tweener.removeTweens(this.indicator);
this._indicator.set_position(bx, by);
this._indicator.set_size(this._selected.box.width,
this._selected.box.height);
}
this._indicator.show();
this._lightbox.highlight(this._selected.window);
this._allocationChangedId =
this._selected.box.connect('notify::allocation',
Lang.bind(this, this._allocationChanged));
} else {
this._label.text = "";
this._indicator.hide();
this._lightbox.highlight(null);
}
}, },
_allocationChanged : function() { _highlightWindow : function(metaWin) {
this._updateSelection(0); this._highlightedWindow = metaWin;
this._lightbox.highlight(this._highlightedWindow.get_compositor_private());
} }
}; };