diff --git a/js/ui/status/keyboard.js b/js/ui/status/keyboard.js index 2e85561e8..fbf56c02d 100644 --- a/js/ui/status/keyboard.js +++ b/js/ui/status/keyboard.js @@ -33,6 +33,33 @@ const KEY_INPUT_SOURCES = 'sources'; const INPUT_SOURCE_TYPE_XKB = 'xkb'; const INPUT_SOURCE_TYPE_IBUS = 'ibus'; +// This is the longest we'll keep the keyboard frozen until an input +// source is active. +const MAX_INPUT_SOURCE_ACTIVATION_TIME = 4000; // ms + +const BUS_NAME = 'org.gnome.SettingsDaemon.Keyboard'; +const OBJECT_PATH = '/org/gnome/SettingsDaemon/Keyboard'; + +const KeyboardManagerInterface = + + + + +; + +const KeyboardManagerProxy = Gio.DBusProxy.makeProxyWrapper(KeyboardManagerInterface); + +function releaseKeyboard() { + if (Main.modalCount > 0) + global.display.unfreeze_keyboard(global.get_current_time()); + else + global.display.ungrab_keyboard(global.get_current_time()); +} + +function holdKeyboard() { + global.freeze_keyboard(global.get_current_time()); +} + const IBusManager = new Lang.Class({ Name: 'IBusManager', @@ -356,6 +383,13 @@ const InputSourceIndicator = new Lang.Class({ this._ibusManager.connect('property-updated', Lang.bind(this, this._ibusPropertyUpdated)); this._inputSourcesChanged(); + this._keyboardManager = new KeyboardManagerProxy(Gio.DBus.session, BUS_NAME, OBJECT_PATH, + function(proxy, error) { + if (error) + log(error.message); + }); + this._keyboardManager.g_default_timeout = MAX_INPUT_SOURCE_ACTIVATION_TIME; + this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem()); this._showLayoutItem = this.menu.addAction(_("Show Keyboard Layout"), Lang.bind(this, this._showLayout)); @@ -479,10 +513,8 @@ const InputSourceIndicator = new Lang.Class({ let is = new InputSource(type, id, displayName, shortName, i); is.connect('activate', Lang.bind(this, function() { - if (this._currentSource && this._currentSource.index == is.index) - return; - this._settings.set_value(KEY_CURRENT_INPUT_SOURCE, - GLib.Variant.new_uint32(is.index)); + holdKeyboard(); + this._keyboardManager.SetInputSourceRemote(is.index, releaseKeyboard); })); if (!(is.shortName in inputSourcesByShortName)) diff --git a/src/shell-global.c b/src/shell-global.c index 889e14612..74af6cd14 100644 --- a/src/shell-global.c +++ b/src/shell-global.c @@ -1009,6 +1009,13 @@ shell_global_end_modal (ShellGlobal *global, meta_plugin_end_modal (global->plugin, timestamp); } +void +shell_global_freeze_keyboard (ShellGlobal *global, + guint32 timestamp) +{ + meta_display_freeze_keyboard (global->meta_display, global->stage_xwindow, timestamp); +} + /* Code to close all file descriptors before we exec; copied from gspawn.c in GLib. * * Authors: Padraig O'Briain, Matthias Clasen, Lennart Poettering diff --git a/src/shell-global.h b/src/shell-global.h index a8df0f5bc..046d0edcb 100644 --- a/src/shell-global.h +++ b/src/shell-global.h @@ -44,6 +44,8 @@ gboolean shell_global_begin_modal (ShellGlobal *global, MetaModalOptions options); void shell_global_end_modal (ShellGlobal *global, guint32 timestamp); +void shell_global_freeze_keyboard (ShellGlobal *global, + guint32 timestamp); typedef enum { SHELL_STAGE_INPUT_MODE_NONREACTIVE,