gnome-shell/js/ui/ctrlAltTab.js
Florian Müllner d3d165243c cleanup: Use non-deprecated key symbols
Clutter originally cluttered its namespace with key symbols, before
prefixing all symbols with KEY. We still use the unprefixed symbols
occasionally, replace them so mutter can drop the deprecated symbols.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/808
2019-11-06 09:42:57 +01:00

191 lines
6.3 KiB
JavaScript

// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported CtrlAltTabManager */
const { Clutter, GObject, Meta, Shell, St } = imports.gi;
const Main = imports.ui.main;
const SwitcherPopup = imports.ui.switcherPopup;
const Params = imports.misc.params;
var POPUP_APPICON_SIZE = 96;
var SortGroup = {
TOP: 0,
MIDDLE: 1,
BOTTOM: 2
};
var CtrlAltTabManager = class CtrlAltTabManager {
constructor() {
this._items = [];
this.addGroup(global.window_group, _("Windows"),
'focus-windows-symbolic', { sortGroup: SortGroup.TOP,
focusCallback: this._focusWindows.bind(this) });
}
addGroup(root, name, icon, params) {
let item = Params.parse(params, { sortGroup: SortGroup.MIDDLE,
proxy: root,
focusCallback: null });
item.root = root;
item.name = name;
item.iconName = icon;
this._items.push(item);
root.connect('destroy', () => this.removeGroup(root));
if (root instanceof St.Widget)
global.focus_manager.add_group(root);
}
removeGroup(root) {
if (root instanceof St.Widget)
global.focus_manager.remove_group(root);
for (let i = 0; i < this._items.length; i++) {
if (this._items[i].root == root) {
this._items.splice(i, 1);
return;
}
}
}
focusGroup(item, timestamp) {
if (item.focusCallback)
item.focusCallback(timestamp);
else
item.root.navigate_focus(null, St.DirectionType.TAB_FORWARD, false);
}
// Sort the items into a consistent order; panel first, tray last,
// and everything else in between, sorted by X coordinate, so that
// they will have the same left-to-right ordering in the
// Ctrl-Alt-Tab dialog as they do onscreen.
_sortItems(a, b) {
if (a.sortGroup != b.sortGroup)
return a.sortGroup - b.sortGroup;
let [ax] = a.proxy.get_transformed_position();
let [bx] = b.proxy.get_transformed_position();
return ax - bx;
}
popup(backward, binding, mask) {
// Start with the set of focus groups that are currently mapped
let items = this._items.filter(item => item.proxy.mapped);
// And add the windows metacity would show in its Ctrl-Alt-Tab list
if (Main.sessionMode.hasWindows && !Main.overview.visible) {
let display = global.display;
let workspaceManager = global.workspace_manager;
let activeWorkspace = workspaceManager.get_active_workspace();
let windows = display.get_tab_list(Meta.TabList.DOCKS,
activeWorkspace);
let windowTracker = Shell.WindowTracker.get_default();
let textureCache = St.TextureCache.get_default();
for (let i = 0; i < windows.length; i++) {
let icon = null;
let iconName = null;
if (windows[i].get_window_type () == Meta.WindowType.DESKTOP) {
iconName = 'video-display-symbolic';
} else {
let app = windowTracker.get_window_app(windows[i]);
if (app)
icon = app.create_icon_texture(POPUP_APPICON_SIZE);
else
icon = textureCache.bind_cairo_surface_property(windows[i],
'icon',
POPUP_APPICON_SIZE);
}
items.push({ name: windows[i].title,
proxy: windows[i].get_compositor_private(),
focusCallback: function(timestamp) {
Main.activateWindow(this, timestamp);
}.bind(windows[i]),
iconActor: icon,
iconName: iconName,
sortGroup: SortGroup.MIDDLE });
}
}
if (!items.length)
return;
items.sort(this._sortItems.bind(this));
if (!this._popup) {
this._popup = new CtrlAltTabPopup(items);
this._popup.show(backward, binding, mask);
this._popup.connect('destroy',
() => {
this._popup = null;
});
}
}
_focusWindows(timestamp) {
global.display.focus_default_window(timestamp);
}
};
var CtrlAltTabPopup = GObject.registerClass(
class CtrlAltTabPopup extends SwitcherPopup.SwitcherPopup {
_init(items) {
super._init(items);
this._switcherList = new CtrlAltTabSwitcher(this._items);
}
_keyPressHandler(keysym, action) {
if (action == Meta.KeyBindingAction.SWITCH_PANELS)
this._select(this._next());
else if (action == Meta.KeyBindingAction.SWITCH_PANELS_BACKWARD)
this._select(this._previous());
else if (keysym == Clutter.KEY_Left)
this._select(this._previous());
else if (keysym == Clutter.KEY_Right)
this._select(this._next());
else
return Clutter.EVENT_PROPAGATE;
return Clutter.EVENT_STOP;
}
_finish(time) {
super._finish(time);
Main.ctrlAltTabManager.focusGroup(this._items[this._selectedIndex], time);
}
});
var CtrlAltTabSwitcher = GObject.registerClass(
class CtrlAltTabSwitcher extends SwitcherPopup.SwitcherList {
_init(items) {
super._init(true);
for (let i = 0; i < items.length; i++)
this._addIcon(items[i]);
}
_addIcon(item) {
let box = new St.BoxLayout({ style_class: 'alt-tab-app',
vertical: true });
let icon = item.iconActor;
if (!icon) {
icon = new St.Icon({ icon_name: item.iconName,
icon_size: POPUP_APPICON_SIZE });
}
box.add_child(icon);
let text = new St.Label({
text: item.name,
x_align: Clutter.ActorAlign.CENTER,
});
box.add_child(text);
this.addItem(box, text);
}
});