[gnome-shell] status/keyboard: Factor out an InputSourceManager class
- From: Rui Matos <rtcm src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-shell] status/keyboard: Factor out an InputSourceManager class
- Date: Thu, 11 Sep 2014 17:36:09 +0000 (UTC)
commit effe6fab3a97d60f14a585e8083b332f58893c25
Author: Rui Matos <tiagomatos gmail com>
Date: Thu May 29 18:42:46 2014 +0200
status/keyboard: Factor out an InputSourceManager class
https://bugzilla.gnome.org/show_bug.cgi?id=736435
js/ui/status/keyboard.js | 376 ++++++++++++++++++++++++++--------------------
1 files changed, 210 insertions(+), 166 deletions(-)
---
diff --git a/js/ui/status/keyboard.js b/js/ui/status/keyboard.js
index 990021b..56752fd 100644
--- a/js/ui/status/keyboard.js
+++ b/js/ui/status/keyboard.js
@@ -147,25 +147,10 @@ const InputSourceSwitcher = new Lang.Class({
}
});
-const InputSourceIndicator = new Lang.Class({
- Name: 'InputSourceIndicator',
- Extends: PanelMenu.Button,
+const InputSourceManager = new Lang.Class({
+ Name: 'InputSourceManager',
_init: function() {
- this.parent(0.0, _("Keyboard"));
-
- this._container = new Shell.GenericContainer();
- this._container.connect('get-preferred-width', Lang.bind(this, this._containerGetPreferredWidth));
- this._container.connect('get-preferred-height', Lang.bind(this, this._containerGetPreferredHeight));
- this._container.connect('allocate', Lang.bind(this, this._containerAllocate));
-
- this._hbox = new St.BoxLayout({ style_class: 'panel-status-menu-box' });
- this._hbox.add_child(this._container);
- this._hbox.add_child(PopupMenu.arrowIcon(St.Side.BOTTOM));
-
- this.actor.add_child(this._hbox);
- this.actor.add_style_class_name('panel-status-button');
-
// All valid input sources currently in the gsettings
// KEY_INPUT_SOURCES list indexed by their index there
this._inputSources = {};
@@ -197,29 +182,16 @@ const InputSourceIndicator = new Lang.Class({
this._xkbInfo = KeyboardManager.getXkbInfo();
- this._propSeparator = new PopupMenu.PopupSeparatorMenuItem();
- this.menu.addMenuItem(this._propSeparator);
- this._propSection = new PopupMenu.PopupMenuSection();
- this.menu.addMenuItem(this._propSection);
- this._propSection.actor.hide();
-
this._ibusReady = false;
this._ibusManager = IBusManager.getIBusManager();
this._ibusManager.connect('ready', Lang.bind(this, this._ibusReadyCallback));
this._ibusManager.connect('properties-registered', Lang.bind(this, this._ibusPropertiesRegistered));
this._ibusManager.connect('property-updated', Lang.bind(this, this._ibusPropertyUpdated));
- this._inputSourcesChanged();
this._keyboardManager = KeyboardManager.getKeyboardManager();
global.display.connect('modifiers-accelerator-activated', Lang.bind(this, this._modifiersSwitcher));
- this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
- this._showLayoutItem = this.menu.addAction(_("Show Keyboard Layout"), Lang.bind(this,
this._showLayout));
-
- Main.sessionMode.connect('updated', Lang.bind(this, this._sessionUpdated));
- this._sessionUpdated();
-
this._sourcesPerWindow = false;
this._focusWindowNotifyId = 0;
this._overviewShowingId = 0;
@@ -228,12 +200,8 @@ const InputSourceIndicator = new Lang.Class({
this._sourcesPerWindowChanged();
},
- _sessionUpdated: function() {
- // re-using "allowSettings" for the keyboard layout is a bit shady,
- // but at least for now it is used as "allow popping up windows
- // from shell menus"; we can always add a separate sessionMode
- // option if need arises.
- this._showLayoutItem.actor.visible = Main.sessionMode.allowSettings;
+ reload: function() {
+ this._inputSourcesChanged();
},
_ibusReadyCallback: function(im, ready) {
@@ -288,7 +256,6 @@ const InputSourceIndicator = new Lang.Class({
},
_currentInputSourceChanged: function() {
- let nVisibleSources = Object.keys(this._inputSources).length;
let newSourceIndex = this._settings.get_uint(KEY_CURRENT_INPUT_SOURCE);
let newSource = this._inputSources[newSourceIndex];
@@ -300,25 +267,11 @@ const InputSourceIndicator = new Lang.Class({
oldSource.indicatorLabel.hide();
}
- if (!newSource || (nVisibleSources < 2 && !newSource.properties)) {
- // This source index might be invalid if we weren't able
- // to build a menu item for it, so we hide ourselves since
- // we can't fix it here. *shrug*
-
- // We also hide if we have only one visible source unless
- // it's an IBus source with properties.
- this.menu.close();
- this.actor.hide();
- return;
- }
-
- this.actor.show();
+ this.emit('current-source-changed');
newSource.menuItem.setOrnament(PopupMenu.Ornament.DOT);
newSource.indicatorLabel.show();
- this._buildPropSection(newSource.properties);
-
for (let i = 1; i < this._mruSources.length; ++i)
if (this._mruSources[i] == newSource) {
let currentSource = this._mruSources.splice(i, 1);
@@ -384,20 +337,17 @@ const InputSourceIndicator = new Lang.Class({
this._ibusSources[is.id] = is;
}
- let menuIndex = 0;
for (let i in this._inputSources) {
let is = this._inputSources[i];
if (inputSourcesByShortName[is.shortName].length > 1) {
let sub = inputSourcesByShortName[is.shortName].indexOf(is) + 1;
is.shortName += String.fromCharCode(0x2080 + sub);
}
-
- this.menu.addMenuItem(is.menuItem, menuIndex++);
-
is.indicatorLabel.hide();
- this._container.add_actor(is.indicatorLabel);
}
+ this.emit('sources-changed');
+
let sourcesList = [];
for (let i in this._inputSources)
sourcesList.push(this._inputSources[i]);
@@ -416,33 +366,6 @@ const InputSourceIndicator = new Lang.Class({
this._currentInputSourceChanged();
},
- _showLayout: function() {
- Main.overview.hide();
-
- let source = this._currentSource;
- let xkbLayout = '';
- let xkbVariant = '';
-
- if (source.type == INPUT_SOURCE_TYPE_XKB) {
- [, , , xkbLayout, xkbVariant] = this._xkbInfo.get_layout_info(source.id);
- } else if (source.type == INPUT_SOURCE_TYPE_IBUS) {
- let engineDesc = this._ibusManager.getEngineDesc(source.id);
- if (engineDesc) {
- xkbLayout = engineDesc.get_layout();
- xkbVariant = '';
- }
- }
-
- if (!xkbLayout || xkbLayout.length == 0)
- return;
-
- let description = xkbLayout;
- if (xkbVariant.length > 0)
- description = description + '\t' + xkbVariant;
-
- Util.spawn(['gkbd-keyboard-display', '-l', description]);
- },
-
_makeEngineShortName: function(engineDesc) {
let symbol = engineDesc.get_symbol();
if (symbol && symbol[0])
@@ -493,6 +416,175 @@ const InputSourceIndicator = new Lang.Class({
return false;
},
+ _getNewInputSource: function(current) {
+ for (let i in this._inputSources) {
+ let is = this._inputSources[i];
+ if (is.type == current.type &&
+ is.id == current.id)
+ return is;
+ }
+ return this._currentSource;
+ },
+
+ _getCurrentWindow: function() {
+ if (Main.overview.visible)
+ return Main.overview;
+ else
+ return global.display.focus_window;
+ },
+
+ _setPerWindowInputSource: function() {
+ let window = this._getCurrentWindow();
+ if (!window)
+ return;
+
+ if (!window._inputSources) {
+ window._inputSources = this._inputSources;
+ window._currentSource = this._currentSource;
+ } else if (window._inputSources == this._inputSources) {
+ window._currentSource.activate();
+ } else {
+ window._inputSources = this._inputSources;
+ window._currentSource = this._getNewInputSource(window._currentSource);
+ window._currentSource.activate();
+ }
+ },
+
+ _sourcesPerWindowChanged: function() {
+ this._sourcesPerWindow = this._settings.get_boolean('per-window');
+
+ if (this._sourcesPerWindow && this._focusWindowNotifyId == 0) {
+ this._focusWindowNotifyId = global.display.connect('notify::focus-window',
+ Lang.bind(this,
this._setPerWindowInputSource));
+ this._overviewShowingId = Main.overview.connect('showing',
+ Lang.bind(this, this._setPerWindowInputSource));
+ this._overviewHiddenId = Main.overview.connect('hidden',
+ Lang.bind(this, this._setPerWindowInputSource));
+ } else if (!this._sourcesPerWindow && this._focusWindowNotifyId != 0) {
+ global.display.disconnect(this._focusWindowNotifyId);
+ this._focusWindowNotifyId = 0;
+ Main.overview.disconnect(this._overviewShowingId);
+ this._overviewShowingId = 0;
+ Main.overview.disconnect(this._overviewHiddenId);
+ this._overviewHiddenId = 0;
+
+ let windows = global.get_window_actors().map(function(w) {
+ return w.meta_window;
+ });
+ for (let i = 0; i < windows.length; ++i) {
+ delete windows[i]._inputSources;
+ delete windows[i]._currentSource;
+ }
+ delete Main.overview._inputSources;
+ delete Main.overview._currentSource;
+ }
+ },
+
+ _changePerWindowSource: function() {
+ if (!this._sourcesPerWindow)
+ return;
+
+ let window = this._getCurrentWindow();
+ if (!window)
+ return;
+
+ window._inputSources = this._inputSources;
+ window._currentSource = this._currentSource;
+ },
+
+ get currentSource() {
+ return this._currentSource;
+ },
+
+ get inputSources() {
+ return this._inputSources;
+ },
+});
+Signals.addSignalMethods(InputSourceManager.prototype);
+
+let _inputSourceManager = null;
+
+function getInputSourceManager() {
+ if (_inputSourceManager == null)
+ _inputSourceManager = new InputSourceManager();
+ return _inputSourceManager;
+}
+
+const InputSourceIndicator = new Lang.Class({
+ Name: 'InputSourceIndicator',
+ Extends: PanelMenu.Button,
+
+ _init: function() {
+ this.parent(0.0, _("Keyboard"));
+
+ this._container = new Shell.GenericContainer();
+ this._container.connect('get-preferred-width', Lang.bind(this, this._containerGetPreferredWidth));
+ this._container.connect('get-preferred-height', Lang.bind(this, this._containerGetPreferredHeight));
+ this._container.connect('allocate', Lang.bind(this, this._containerAllocate));
+
+ this._hbox = new St.BoxLayout({ style_class: 'panel-status-menu-box' });
+ this._hbox.add_child(this._container);
+ this._hbox.add_child(PopupMenu.arrowIcon(St.Side.BOTTOM));
+
+ this.actor.add_child(this._hbox);
+ this.actor.add_style_class_name('panel-status-button');
+
+ this._propSeparator = new PopupMenu.PopupSeparatorMenuItem();
+ this.menu.addMenuItem(this._propSeparator);
+ this._propSection = new PopupMenu.PopupMenuSection();
+ this.menu.addMenuItem(this._propSection);
+ this._propSection.actor.hide();
+
+ this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
+ this._showLayoutItem = this.menu.addAction(_("Show Keyboard Layout"), Lang.bind(this,
this._showLayout));
+
+ Main.sessionMode.connect('updated', Lang.bind(this, this._sessionUpdated));
+ this._sessionUpdated();
+
+ this._inputSourceManager = getInputSourceManager();
+ this._inputSourceManager.connect('sources-changed', Lang.bind(this, this._sourcesChanged));
+ this._inputSourceManager.connect('current-source-changed', Lang.bind(this,
this._currentSourceChanged));
+ this._inputSourceManager.reload();
+ },
+
+ _sessionUpdated: function() {
+ // re-using "allowSettings" for the keyboard layout is a bit shady,
+ // but at least for now it is used as "allow popping up windows
+ // from shell menus"; we can always add a separate sessionMode
+ // option if need arises.
+ this._showLayoutItem.actor.visible = Main.sessionMode.allowSettings;
+ },
+
+ _sourcesChanged: function() {
+ let menuIndex = 0;
+ for (let i in this._inputSourceManager.inputSources) {
+ let is = this._inputSourceManager.inputSources[i];
+ this.menu.addMenuItem(is.menuItem, menuIndex++);
+ this._container.add_actor(is.indicatorLabel);
+ }
+ },
+
+ _currentSourceChanged: function() {
+ let nVisibleSources = Object.keys(this._inputSourceManager.inputSources).length;
+ let newSource = this._inputSourceManager.currentSource;
+
+ if (!newSource || (nVisibleSources < 2 && !newSource.properties)) {
+ // This source index might be invalid if we weren't able
+ // to build a menu item for it, so we hide ourselves since
+ // we can't fix it here. *shrug*
+
+ // We also hide if we have only one visible source unless
+ // it's an IBus source with properties.
+ this.menu.close();
+ this.actor.hide();
+ return;
+ }
+
+ this.actor.show();
+
+ this._buildPropSection(newSource.properties);
+ },
+
_buildPropSection: function(properties) {
this._propSeparator.actor.hide();
this._propSection.actor.hide();
@@ -510,6 +602,7 @@ const InputSourceIndicator = new Lang.Class({
if (!props)
return;
+ let ibusManager = IBusManager.getIBusManager();
let radioGroup = [];
let p;
for (let i = 0; (p = props.get(i)) != null; ++i) {
@@ -552,13 +645,13 @@ const InputSourceIndicator = new Lang.Class({
if (group[i] == item) {
item.setOrnament(PopupMenu.Ornament.DOT);
item.prop.set_state(IBus.PropState.CHECKED);
- this._ibusManager.activateProperty(item.prop.get_key(),
- IBus.PropState.CHECKED);
+ ibusManager.activateProperty(item.prop.get_key(),
+ IBus.PropState.CHECKED);
} else {
group[i].setOrnament(PopupMenu.Ornament.NONE);
group[i].prop.set_state(IBus.PropState.UNCHECKED);
- this._ibusManager.activateProperty(group[i].prop.get_key(),
- IBus.PropState.UNCHECKED);
+ ibusManager.activateProperty(group[i].prop.get_key(),
+ IBus.PropState.UNCHECKED);
}
}
}));
@@ -570,12 +663,12 @@ const InputSourceIndicator = new Lang.Class({
item.connect('toggled', Lang.bind(this, function() {
if (item.state) {
item.prop.set_state(IBus.PropState.CHECKED);
- this._ibusManager.activateProperty(item.prop.get_key(),
- IBus.PropState.CHECKED);
+ ibusManager.activateProperty(item.prop.get_key(),
+ IBus.PropState.CHECKED);
} else {
item.prop.set_state(IBus.PropState.UNCHECKED);
- this._ibusManager.activateProperty(item.prop.get_key(),
- IBus.PropState.UNCHECKED);
+ ibusManager.activateProperty(item.prop.get_key(),
+ IBus.PropState.UNCHECKED);
}
}));
break;
@@ -584,8 +677,8 @@ const InputSourceIndicator = new Lang.Class({
item = new PopupMenu.PopupMenuItem(prop.get_label().get_text());
item.prop = prop;
item.connect('activate', Lang.bind(this, function() {
- this._ibusManager.activateProperty(item.prop.get_key(),
- item.prop.get_state());
+ ibusManager.activateProperty(item.prop.get_key(),
+ item.prop.get_state());
}));
break;
@@ -603,80 +696,31 @@ const InputSourceIndicator = new Lang.Class({
}
},
- _getNewInputSource: function(current) {
- for (let i in this._inputSources) {
- let is = this._inputSources[i];
- if (is.type == current.type &&
- is.id == current.id)
- return is;
- }
- return this._currentSource;
- },
-
- _getCurrentWindow: function() {
- if (Main.overview.visible)
- return Main.overview;
- else
- return global.display.focus_window;
- },
-
- _setPerWindowInputSource: function() {
- let window = this._getCurrentWindow();
- if (!window)
- return;
-
- if (!window._inputSources) {
- window._inputSources = this._inputSources;
- window._currentSource = this._currentSource;
- } else if (window._inputSources == this._inputSources) {
- window._currentSource.activate();
- } else {
- window._inputSources = this._inputSources;
- window._currentSource = this._getNewInputSource(window._currentSource);
- window._currentSource.activate();
- }
- },
-
- _sourcesPerWindowChanged: function() {
- this._sourcesPerWindow = this._settings.get_boolean('per-window');
+ _showLayout: function() {
+ Main.overview.hide();
- if (this._sourcesPerWindow && this._focusWindowNotifyId == 0) {
- this._focusWindowNotifyId = global.display.connect('notify::focus-window',
- Lang.bind(this,
this._setPerWindowInputSource));
- this._overviewShowingId = Main.overview.connect('showing',
- Lang.bind(this, this._setPerWindowInputSource));
- this._overviewHiddenId = Main.overview.connect('hidden',
- Lang.bind(this, this._setPerWindowInputSource));
- } else if (!this._sourcesPerWindow && this._focusWindowNotifyId != 0) {
- global.display.disconnect(this._focusWindowNotifyId);
- this._focusWindowNotifyId = 0;
- Main.overview.disconnect(this._overviewShowingId);
- this._overviewShowingId = 0;
- Main.overview.disconnect(this._overviewHiddenId);
- this._overviewHiddenId = 0;
+ let source = this._inputSourceManager.currentSource;
+ let xkbLayout = '';
+ let xkbVariant = '';
- let windows = global.get_window_actors().map(function(w) {
- return w.meta_window;
- });
- for (let i = 0; i < windows.length; ++i) {
- delete windows[i]._inputSources;
- delete windows[i]._currentSource;
+ if (source.type == INPUT_SOURCE_TYPE_XKB) {
+ [, , , xkbLayout, xkbVariant] = KeyboardManager.getXkbInfo().get_layout_info(source.id);
+ } else if (source.type == INPUT_SOURCE_TYPE_IBUS) {
+ let engineDesc = IBusManager.getIBusManager().getEngineDesc(source.id);
+ if (engineDesc) {
+ xkbLayout = engineDesc.get_layout();
+ xkbVariant = '';
}
- delete Main.overview._inputSources;
- delete Main.overview._currentSource;
}
- },
- _changePerWindowSource: function() {
- if (!this._sourcesPerWindow)
+ if (!xkbLayout || xkbLayout.length == 0)
return;
- let window = this._getCurrentWindow();
- if (!window)
- return;
+ let description = xkbLayout;
+ if (xkbVariant.length > 0)
+ description = description + '\t' + xkbVariant;
- window._inputSources = this._inputSources;
- window._currentSource = this._currentSource;
+ Util.spawn(['gkbd-keyboard-display', '-l', description]);
},
_containerGetPreferredWidth: function(container, for_height, alloc) {
@@ -685,8 +729,8 @@ const InputSourceIndicator = new Lang.Class({
// for those we don't actually display.
let max_min_width = 0, max_natural_width = 0;
- for (let i in this._inputSources) {
- let is = this._inputSources[i];
+ for (let i in this._inputSourceManager.inputSources) {
+ let is = this._inputSourceManager.inputSources[i];
let [min_width, natural_width] = is.indicatorLabel.get_preferred_width(for_height);
max_min_width = Math.max(max_min_width, min_width);
max_natural_width = Math.max(max_natural_width, natural_width);
@@ -699,8 +743,8 @@ const InputSourceIndicator = new Lang.Class({
_containerGetPreferredHeight: function(container, for_width, alloc) {
let max_min_height = 0, max_natural_height = 0;
- for (let i in this._inputSources) {
- let is = this._inputSources[i];
+ for (let i in this._inputSourceManager.inputSources) {
+ let is = this._inputSourceManager.inputSources[i];
let [min_height, natural_height] = is.indicatorLabel.get_preferred_height(for_width);
max_min_height = Math.max(max_min_height, min_height);
max_natural_height = Math.max(max_natural_height, natural_height);
@@ -717,8 +761,8 @@ const InputSourceIndicator = new Lang.Class({
box.y2 -= box.y1;
box.y1 = 0;
- for (let i in this._inputSources) {
- let is = this._inputSources[i];
+ for (let i in this._inputSourceManager.inputSources) {
+ let is = this._inputSourceManager.inputSources[i];
is.indicatorLabel.allocate_align_fill(box, 0.5, 0.5, false, false, flags);
}
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]