status/keyboard: Add an Alt+Tab like input source switcher

https://bugzilla.gnome.org/show_bug.cgi?id=682315
This commit is contained in:
Rui Matos 2012-12-10 20:35:29 +01:00
parent 6eef830ba4
commit f61548234a
2 changed files with 100 additions and 0 deletions

View File

@ -2431,3 +2431,8 @@ StScrollBar StButton#vhandle:active {
padding-bottom: 0px; padding-bottom: 0px;
} }
.input-source-switcher-symbol {
font-size: 42pt;
width: 96px;
height: 96px;
}

View File

@ -1,9 +1,11 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter;
const Gio = imports.gi.Gio; const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib; const GLib = imports.gi.GLib;
const GnomeDesktop = imports.gi.GnomeDesktop; const GnomeDesktop = imports.gi.GnomeDesktop;
const Lang = imports.lang; const Lang = imports.lang;
const Meta = imports.gi.Meta;
const Shell = imports.gi.Shell; const Shell = imports.gi.Shell;
const Signals = imports.signals; const Signals = imports.signals;
const St = imports.gi.St; const St = imports.gi.St;
@ -21,6 +23,7 @@ try {
const Main = imports.ui.main; const Main = imports.ui.main;
const PopupMenu = imports.ui.popupMenu; const PopupMenu = imports.ui.popupMenu;
const PanelMenu = imports.ui.panelMenu; const PanelMenu = imports.ui.panelMenu;
const SwitcherPopup = imports.ui.switcherPopup;
const Util = imports.misc.util; const Util = imports.misc.util;
const DESKTOP_INPUT_SOURCES_SCHEMA = 'org.gnome.desktop.input-sources'; const DESKTOP_INPUT_SOURCES_SCHEMA = 'org.gnome.desktop.input-sources';
@ -227,6 +230,77 @@ const InputSource = new Lang.Class({
}); });
Signals.addSignalMethods(InputSource.prototype); Signals.addSignalMethods(InputSource.prototype);
const InputSourcePopup = new Lang.Class({
Name: 'InputSourcePopup',
Extends: SwitcherPopup.SwitcherPopup,
_init: function(items, action, actionBackward) {
this.parent(items);
this._action = action;
this._actionBackward = actionBackward;
},
_createSwitcher: function() {
this._switcherList = new InputSourceSwitcher(this._items);
return true;
},
_initialSelection: function(backward, binding) {
if (binding == 'switch-input-source') {
if (backward)
this._selectedIndex = this._items.length - 1;
} else if (binding == 'switch-input-source-backward') {
if (!backward)
this._selectedIndex = this._items.length - 1;
}
this._select(this._selectedIndex);
},
_keyPressHandler: function(keysym, backwards, action) {
if (action == this._action)
this._select(backwards ? this._previous() : this._next());
else if (action == this._actionBackward)
this._select(backwards ? this._next() : this._previous());
else if (keysym == Clutter.Left)
this._select(this._previous());
else if (keysym == Clutter.Right)
this._select(this._next());
},
_finish : function() {
this.parent();
this._items[this._selectedIndex].activate();
},
});
const InputSourceSwitcher = new Lang.Class({
Name: 'InputSourceSwitcher',
Extends: SwitcherPopup.SwitcherList,
_init: function(items) {
this.parent(true);
for (let i = 0; i < items.length; i++)
this._addIcon(items[i]);
},
_addIcon: function(item) {
let box = new St.BoxLayout({ vertical: true });
let bin = new St.Bin({ style_class: 'input-source-switcher-symbol' });
let symbol = new St.Label({ text: item.shortName });
bin.set_child(symbol);
box.add(bin, { x_fill: false, y_fill: false } );
let text = new St.Label({ text: item.displayName });
box.add(text, { x_fill: false });
this.addItem(box, text);
}
});
const InputSourceIndicator = new Lang.Class({ const InputSourceIndicator = new Lang.Class({
Name: 'InputSourceIndicator', Name: 'InputSourceIndicator',
Extends: PanelMenu.Button, Extends: PanelMenu.Button,
@ -254,6 +328,19 @@ const InputSourceIndicator = new Lang.Class({
// All valid input sources currently in the gsettings // All valid input sources currently in the gsettings
// KEY_INPUT_SOURCES list ordered by most recently used // KEY_INPUT_SOURCES list ordered by most recently used
this._mruSources = []; this._mruSources = [];
this._keybindingAction =
Main.wm.addKeybinding('switch-input-source',
new Gio.Settings({ schema: "org.gnome.shell.keybindings" }),
Meta.KeyBindingFlags.REVERSES,
Main.KeybindingMode.ALL,
Lang.bind(this, this._switchInputSource));
this._keybindingActionBackward =
Main.wm.addKeybinding('switch-input-source-backward',
new Gio.Settings({ schema: "org.gnome.shell.keybindings" }),
Meta.KeyBindingFlags.REVERSES |
Meta.KeyBindingFlags.REVERSED,
Main.KeybindingMode.ALL,
Lang.bind(this, this._switchInputSource));
this._settings = new Gio.Settings({ schema: DESKTOP_INPUT_SOURCES_SCHEMA }); this._settings = new Gio.Settings({ schema: DESKTOP_INPUT_SOURCES_SCHEMA });
this._settings.connect('changed::' + KEY_CURRENT_INPUT_SOURCE, Lang.bind(this, this._currentInputSourceChanged)); this._settings.connect('changed::' + KEY_CURRENT_INPUT_SOURCE, Lang.bind(this, this._currentInputSourceChanged));
this._settings.connect('changed::' + KEY_INPUT_SOURCES, Lang.bind(this, this._inputSourcesChanged)); this._settings.connect('changed::' + KEY_INPUT_SOURCES, Lang.bind(this, this._inputSourcesChanged));
@ -298,6 +385,14 @@ const InputSourceIndicator = new Lang.Class({
this._inputSourcesChanged(); this._inputSourcesChanged();
}, },
_switchInputSource: function(display, screen, window, binding) {
let popup = new InputSourcePopup(this._mruSources, this._keybindingAction, this._keybindingActionBackward);
let modifiers = binding.get_modifiers();
let backwards = modifiers & Meta.VirtualModifier.SHIFT_MASK;
if (!popup.show(backwards, binding.get_name(), binding.get_mask()))
popup.destroy();
},
_currentInputSourceChanged: function() { _currentInputSourceChanged: function() {
let nVisibleSources = Object.keys(this._inputSources).length; let nVisibleSources = Object.keys(this._inputSources).length;
let newSourceIndex = this._settings.get_uint(KEY_CURRENT_INPUT_SOURCE); let newSourceIndex = this._settings.get_uint(KEY_CURRENT_INPUT_SOURCE);