Compare commits
	
		
			7 Commits
		
	
	
		
			wip/lockdo
			...
			wip/input-
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					d4802861ed | ||
| 
						 | 
					a8fa0b8146 | ||
| 
						 | 
					cf0bb62f40 | ||
| 
						 | 
					de8106967d | ||
| 
						 | 
					1a24f061cf | ||
| 
						 | 
					e038845458 | ||
| 
						 | 
					b03273c765 | 
@@ -2040,3 +2040,30 @@ StScrollBar StButton#vhandle:hover
 | 
			
		||||
    -arrow-rise: 10px;
 | 
			
		||||
    -boxpointer-gap: 5px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Candidate Window */
 | 
			
		||||
.candidate-panel {
 | 
			
		||||
    min-width: 100px;
 | 
			
		||||
    padding: .5em;
 | 
			
		||||
    spacing: 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.candidate-area {
 | 
			
		||||
    padding-top: 5px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.candidate-label {
 | 
			
		||||
    cursor: pointer;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.candidate-hlabel-content {
 | 
			
		||||
    padding: 0em .5em 0em 0em;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.candidate-htext-content {
 | 
			
		||||
    padding: 0em;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.candidate-vcontent {
 | 
			
		||||
    padding: 0em .5em 0em 0em;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -84,6 +84,7 @@ nobase_dist_js_DATA = 	\
 | 
			
		||||
	ui/shellDBus.js		\
 | 
			
		||||
	ui/statusIconDispatcher.js	\
 | 
			
		||||
	ui/status/accessibility.js	\
 | 
			
		||||
	ui/status/candidatePanel.js	\
 | 
			
		||||
	ui/status/keyboard.js	\
 | 
			
		||||
	ui/status/network.js	\
 | 
			
		||||
	ui/status/power.js	\
 | 
			
		||||
 
 | 
			
		||||
@@ -37,7 +37,7 @@ const STANDARD_STATUS_AREA_SHELL_IMPLEMENTATION = {
 | 
			
		||||
    'a11y': imports.ui.status.accessibility.ATIndicator,
 | 
			
		||||
    'volume': imports.ui.status.volume.Indicator,
 | 
			
		||||
    'battery': imports.ui.status.power.Indicator,
 | 
			
		||||
    'keyboard': imports.ui.status.keyboard.XKBIndicator,
 | 
			
		||||
    'keyboard': imports.ui.status.keyboard.InputSourceIndicator,
 | 
			
		||||
    'userMenu': imports.ui.userMenu.UserMenuButton
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@@ -55,7 +55,7 @@ const GDM_STATUS_AREA_SHELL_IMPLEMENTATION = {
 | 
			
		||||
    'a11y': imports.ui.status.accessibility.ATIndicator,
 | 
			
		||||
    'volume': imports.ui.status.volume.Indicator,
 | 
			
		||||
    'battery': imports.ui.status.power.Indicator,
 | 
			
		||||
    'keyboard': imports.ui.status.keyboard.XKBIndicator,
 | 
			
		||||
    'keyboard': imports.ui.status.keyboard.InputSourceIndicator,
 | 
			
		||||
    'powerMenu': imports.gdm.powerMenu.PowerMenuButton
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										584
									
								
								js/ui/status/candidatePanel.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										584
									
								
								js/ui/status/candidatePanel.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,584 @@
 | 
			
		||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright 2012 Red Hat, Inc.
 | 
			
		||||
 * Copyright 2012 Peng Huang <shawn.p.huang@gmail.com>
 | 
			
		||||
 * Copyright 2012 Takao Fujiwara <tfujiwar@redhat.com>
 | 
			
		||||
 * Copyright 2012 Tiger Soldier <tigersoldi@gmail.com>
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU Lesser General Public License as
 | 
			
		||||
 * published by the Free Software Foundation, either version 2.1 of
 | 
			
		||||
 * the License, or (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope it will be useful, but WITHOUT ANY
 | 
			
		||||
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 | 
			
		||||
 * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for
 | 
			
		||||
 * more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
const St = imports.gi.St;
 | 
			
		||||
const GLib = imports.gi.GLib;
 | 
			
		||||
const IBus = imports.gi.IBus;
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
const Signals = imports.signals;
 | 
			
		||||
const Shell = imports.gi.Shell;
 | 
			
		||||
 | 
			
		||||
const BoxPointer = imports.ui.boxpointer;
 | 
			
		||||
const Main = imports.ui.main;
 | 
			
		||||
const PopupMenu = imports.ui.popupMenu;
 | 
			
		||||
 | 
			
		||||
const ORIENTATION_HORIZONTAL  = 0;
 | 
			
		||||
const ORIENTATION_VERTICAL    = 1;
 | 
			
		||||
const ORIENTATION_SYSTEM      = 2;
 | 
			
		||||
 | 
			
		||||
const StCandidateArea = new Lang.Class({
 | 
			
		||||
    Name: 'StCandidateArea',
 | 
			
		||||
 | 
			
		||||
    _init: function(orientation) {
 | 
			
		||||
        this.actor = new St.BoxLayout({ style_class: 'candidate-area' });
 | 
			
		||||
        this._orientation = orientation;
 | 
			
		||||
        this._labels = [];
 | 
			
		||||
        this._labelBoxes = [];
 | 
			
		||||
        this._createUI();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _removeOldWidgets: function() {
 | 
			
		||||
        this.actor.destroy_all_children();
 | 
			
		||||
        this._labels = [];
 | 
			
		||||
        this._labelBoxes = [];
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _createUI: function() {
 | 
			
		||||
        let vbox = null;
 | 
			
		||||
        let hbox = null;
 | 
			
		||||
        if (this._orientation == ORIENTATION_VERTICAL) {
 | 
			
		||||
            vbox = new St.BoxLayout({ vertical: true,
 | 
			
		||||
                                      style_class: 'candidate-vertical' });
 | 
			
		||||
            this.actor.add_child(vbox,
 | 
			
		||||
                                 { expand: true,
 | 
			
		||||
                                   x_fill: true,
 | 
			
		||||
                                   y_fill: true
 | 
			
		||||
                                 });
 | 
			
		||||
        } else {
 | 
			
		||||
            hbox = new St.BoxLayout({ vertical: false,
 | 
			
		||||
                                      style_class: 'candidate-horizontal' });
 | 
			
		||||
            this.actor.add_child(hbox,
 | 
			
		||||
                                 { expand: true,
 | 
			
		||||
                                   x_fill: true,
 | 
			
		||||
                                   y_fill: true
 | 
			
		||||
                                 });
 | 
			
		||||
        }
 | 
			
		||||
        for (let i = 0; i < 16; i++) {
 | 
			
		||||
            let label1 = new St.Label({ text: '1234567890abcdef'.charAt(i) + '.',
 | 
			
		||||
                                        style_class: 'popup-menu-item',
 | 
			
		||||
                                        reactive: true });
 | 
			
		||||
 | 
			
		||||
            let label2 = new St.Label({ text: '' ,
 | 
			
		||||
                                        style_class: 'popup-menu-item',
 | 
			
		||||
                                        reactive: true });
 | 
			
		||||
 | 
			
		||||
            if (this._orientation == ORIENTATION_VERTICAL) {
 | 
			
		||||
                let candidateHBox = new St.BoxLayout({vertical: false});
 | 
			
		||||
                let labelBox = new St.Bin({ style_class: 'candidate-hlabel-content' });
 | 
			
		||||
                labelBox.set_child(label1);
 | 
			
		||||
                labelBox.set_fill(true, true);
 | 
			
		||||
                let textBox = new St.Bin({ style_class: 'candidate-htext-content' });
 | 
			
		||||
 | 
			
		||||
                textBox.set_child(label2);
 | 
			
		||||
                textBox.set_fill(true, true);
 | 
			
		||||
                candidateHBox.add_child(labelBox,
 | 
			
		||||
                                        { expand: false,
 | 
			
		||||
                                          x_fill: false,
 | 
			
		||||
                                          y_fill: true
 | 
			
		||||
                                        });
 | 
			
		||||
                candidateHBox.add_child(textBox,
 | 
			
		||||
                                        { expand: true,
 | 
			
		||||
                                          x_fill: true,
 | 
			
		||||
                                          y_fill: true
 | 
			
		||||
                                        });
 | 
			
		||||
                vbox.add_child(candidateHBox);
 | 
			
		||||
                this._labelBoxes.push(candidateHBox);
 | 
			
		||||
            } else {
 | 
			
		||||
                let candidateHBox = new St.BoxLayout({ style_class: 'candidate-vcontent',
 | 
			
		||||
                                                       vertical: false });
 | 
			
		||||
                candidateHBox.add_child(label1);
 | 
			
		||||
                candidateHBox.add_child(label2);
 | 
			
		||||
                hbox.add_child(candidateHBox);
 | 
			
		||||
                this._labelBoxes.push(candidateHBox);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            this._labels.push([label1, label2]);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        for (let i = 0; i < this._labels.length; i++) {
 | 
			
		||||
            for(let j = 0; j < this._labels[i].length; j++) {
 | 
			
		||||
                let widget = this._labels[i][j];
 | 
			
		||||
                widget.candidateIndex = i;
 | 
			
		||||
                widget.connect('button-press-event',
 | 
			
		||||
                               Lang.bind(this, function (widget, event) {
 | 
			
		||||
                                   this._candidateClickedCB(widget, event);
 | 
			
		||||
                               }));
 | 
			
		||||
                widget.connect('enter-event',
 | 
			
		||||
                               function(widget, event) {
 | 
			
		||||
                                   widget.add_style_pseudo_class('hover');
 | 
			
		||||
                               });
 | 
			
		||||
                widget.connect('leave-event',
 | 
			
		||||
                               function(widget, event) {
 | 
			
		||||
                                   widget.remove_style_pseudo_class('hover');
 | 
			
		||||
                               });
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _recreateUI: function() {
 | 
			
		||||
        this._removeOldWidgets();
 | 
			
		||||
        this._createUI();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _candidateClickedCB: function(widget, event) {
 | 
			
		||||
        this.emit('candidate-clicked',
 | 
			
		||||
                  widget.candidateIndex,
 | 
			
		||||
                  event.get_button(),
 | 
			
		||||
                  event.get_state());
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    setLabels: function(labels) {
 | 
			
		||||
        if (!labels || labels.length == 0) {
 | 
			
		||||
            for (let i = 0; i < 16; i++) {
 | 
			
		||||
                this._labels[i][0].set_text('1234567890abcdef'.charAt(i) + '.');
 | 
			
		||||
            }
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        for (let i = 0; i < labels.length && i < this._labels.length; i++) {
 | 
			
		||||
            /* Use a ClutterActor attribute of Shell's theme instead of
 | 
			
		||||
             * Pango.AttrList for the lookup window GUI and
 | 
			
		||||
             * can ignore 'attrs' simply from IBus engines?
 | 
			
		||||
             */
 | 
			
		||||
            let [text, attrs] = labels[i];
 | 
			
		||||
            this._labels[i][0].set_text(text);
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    setCandidates: function(candidates, focusCandidate, showCursor) {
 | 
			
		||||
        if (focusCandidate == undefined) {
 | 
			
		||||
            focusCandidate = 0;
 | 
			
		||||
        }
 | 
			
		||||
        if (showCursor == undefined) {
 | 
			
		||||
            showCursor = true;
 | 
			
		||||
        }
 | 
			
		||||
        if (candidates.length > this._labels.length) {
 | 
			
		||||
            assert();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        for (let i = 0; i < candidates.length; i++) {
 | 
			
		||||
            /* Use a ClutterActor attribute of Shell's theme instead of
 | 
			
		||||
             * Pango.AttrList for the lookup window GUI and
 | 
			
		||||
             * can ignore 'attrs' simply from IBus engines?
 | 
			
		||||
             */
 | 
			
		||||
            let [text, attrs] = candidates[i];
 | 
			
		||||
            if (i == focusCandidate && showCursor) {
 | 
			
		||||
                this._labels[i][1].add_style_pseudo_class('active');
 | 
			
		||||
            } else {
 | 
			
		||||
                this._labels[i][1].remove_style_pseudo_class('active');
 | 
			
		||||
            }
 | 
			
		||||
            this._labels[i][1].set_text(text);
 | 
			
		||||
            this._labelBoxes[i].show();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        for (let i = this._labelBoxes.length - 1; i >= candidates.length; i--) {
 | 
			
		||||
            this._labelBoxes[i].hide();
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    setOrientation: function(orientation) {
 | 
			
		||||
        if (orientation == this._orientation)
 | 
			
		||||
            return;
 | 
			
		||||
        this._orientation = orientation;
 | 
			
		||||
        this._recreateUI();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    showAll: function() {
 | 
			
		||||
        this.actor.show();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    hideAll: function() {
 | 
			
		||||
        this.actor.hide();
 | 
			
		||||
    },
 | 
			
		||||
});
 | 
			
		||||
Signals.addSignalMethods(StCandidateArea.prototype);
 | 
			
		||||
 | 
			
		||||
const CandidatePanel = new Lang.Class({
 | 
			
		||||
    Name: 'CandidatePanel',
 | 
			
		||||
 | 
			
		||||
    _init: function() {
 | 
			
		||||
        this._orientation = ORIENTATION_VERTICAL;
 | 
			
		||||
        this._currentOrientation = this._orientation;
 | 
			
		||||
        this._preeditVisible = false;
 | 
			
		||||
        this._auxStringVisible = false;
 | 
			
		||||
        this._lookupTableVisible = false;
 | 
			
		||||
        this._lookupTable = null;
 | 
			
		||||
 | 
			
		||||
        this._cursorLocation = [0, 0, 0, 0];
 | 
			
		||||
        this._movedCursorLocation = null;
 | 
			
		||||
 | 
			
		||||
        this._initSt();
 | 
			
		||||
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _initSt: function() {
 | 
			
		||||
        this._arrowSide = St.Side.TOP;
 | 
			
		||||
        this._arrowAlignment = 0.0;
 | 
			
		||||
        this._boxPointer = new BoxPointer.BoxPointer(this._arrowSide,
 | 
			
		||||
                                                     { x_fill: true,
 | 
			
		||||
                                                       y_fill: true,
 | 
			
		||||
                                                       x_align: St.Align.START });
 | 
			
		||||
        this.actor = this._boxPointer.actor;
 | 
			
		||||
        this.actor._delegate = this;
 | 
			
		||||
        this.actor.style_class = 'popup-menu-boxpointer';
 | 
			
		||||
        this.actor.add_style_class_name('popup-menu');
 | 
			
		||||
        this.actor.add_style_class_name('candidate-panel');
 | 
			
		||||
        this._cursorActor = new Shell.GenericContainer();
 | 
			
		||||
        Main.uiGroup.add_actor(this.actor);
 | 
			
		||||
        Main.uiGroup.add_actor(this._cursorActor);
 | 
			
		||||
 | 
			
		||||
        this._stCandidatePanel = new St.BoxLayout({ style_class: 'candidate-panel',
 | 
			
		||||
                                                    vertical: true });
 | 
			
		||||
        this._boxPointer.bin.set_child(this._stCandidatePanel);
 | 
			
		||||
 | 
			
		||||
        this._stPreeditLabel = new St.Label({ style_class: 'popup-menu-item',
 | 
			
		||||
                                              text: '' });
 | 
			
		||||
        if (!this._preeditVisible) {
 | 
			
		||||
            this._stPreeditLabel.hide();
 | 
			
		||||
        }
 | 
			
		||||
        this._stAuxLabel = new St.Label({ style_class: 'popup-menu-item',
 | 
			
		||||
                                          text: '' });
 | 
			
		||||
        if (!this._auxVisible) {
 | 
			
		||||
            this._stAuxLabel.hide();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._separator = new PopupMenu.PopupSeparatorMenuItem();
 | 
			
		||||
        if (!this._preeditVisible && !this._auxVisible) {
 | 
			
		||||
            this._separator.actor.hide();
 | 
			
		||||
        }
 | 
			
		||||
        // create candidates area
 | 
			
		||||
        this._stCandidateArea = new StCandidateArea(this._currentOrientation);
 | 
			
		||||
        this._stCandidateArea.connect('candidate-clicked',
 | 
			
		||||
                                      Lang.bind(this, function(x, i, b, s) {
 | 
			
		||||
                                                this.emit('candidate-clicked', i, b, s);}));
 | 
			
		||||
        this.updateLookupTable(this._lookupTable, this._lookupTableVisible);
 | 
			
		||||
 | 
			
		||||
        // TODO: page up/down GUI
 | 
			
		||||
 | 
			
		||||
        this._packAllStWidgets();
 | 
			
		||||
        this._isVisible = true;
 | 
			
		||||
        this.hideAll();
 | 
			
		||||
        this._checkShowStates();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _packAllStWidgets: function() {
 | 
			
		||||
        this._stCandidatePanel.add_child(this._stPreeditLabel,
 | 
			
		||||
                                         { x_fill: true,
 | 
			
		||||
                                           y_fill: false,
 | 
			
		||||
                                           x_align: St.Align.MIDDLE,
 | 
			
		||||
                                           y_align: St.Align.START });
 | 
			
		||||
        this._stCandidatePanel.add_child(this._stAuxLabel,
 | 
			
		||||
                                         { x_fill: true,
 | 
			
		||||
                                           y_fill: false,
 | 
			
		||||
                                           x_align: St.Align.MIDDLE,
 | 
			
		||||
                                           y_align: St.Align.MIDDLE });
 | 
			
		||||
        this._stCandidatePanel.add_child(this._separator.actor,
 | 
			
		||||
                                         { x_fill: true,
 | 
			
		||||
                                           y_fill: false,
 | 
			
		||||
                                           x_align: St.Align.MIDDLE,
 | 
			
		||||
                                           y_align: St.Align.MIDDLE });
 | 
			
		||||
        this._stCandidatePanel.add_child(this._stCandidateArea.actor,
 | 
			
		||||
                                         { x_fill: true,
 | 
			
		||||
                                           y_fill: false,
 | 
			
		||||
                                           x_align: St.Align.MIDDLE,
 | 
			
		||||
                                           y_align: St.Align.END });
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    showPreeditText: function() {
 | 
			
		||||
        this._preeditVisible = true;
 | 
			
		||||
        this._stPreeditLabel.show();
 | 
			
		||||
        this._checkShowStates();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    hidePreeditText: function() {
 | 
			
		||||
        this._preeditVisible = false;
 | 
			
		||||
        this._checkShowStates();
 | 
			
		||||
        this._stPreeditLabel.hide();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    updatePreeditText: function(text, cursorPos, visible) {
 | 
			
		||||
        if (visible) {
 | 
			
		||||
            this.showPreeditText();
 | 
			
		||||
        } else {
 | 
			
		||||
            this.hidePreeditText();
 | 
			
		||||
        }
 | 
			
		||||
        let str = text.get_text();
 | 
			
		||||
        this._stPreeditLabel.set_text(str);
 | 
			
		||||
 | 
			
		||||
        let attrs = text.get_attributes();
 | 
			
		||||
        for (let i = 0; attrs != null && attrs.get(i) != null; i++) {
 | 
			
		||||
            let attr = attrs.get(i);
 | 
			
		||||
            if (attr.get_attr_type() == IBus.AttrType.BACKGROUND) {
 | 
			
		||||
                let startIndex = attr.get_start_index();
 | 
			
		||||
                let endIndex = attr.get_end_index();
 | 
			
		||||
                let len = GLib.utf8_strlen(str, -1);
 | 
			
		||||
                let markup = '';
 | 
			
		||||
                if (startIndex == 0 &&
 | 
			
		||||
                    endIndex == GLib.utf8_strlen(str, -1)) {
 | 
			
		||||
                    markup = markup.concat(str);
 | 
			
		||||
                } else {
 | 
			
		||||
                    if (startIndex > 0) {
 | 
			
		||||
                        markup = markup.concat(GLib.utf8_substring(str,
 | 
			
		||||
                                                                   0,
 | 
			
		||||
                                                                   startIndex));
 | 
			
		||||
                    }
 | 
			
		||||
                    if (startIndex != endIndex) {
 | 
			
		||||
                        markup = markup.concat('<span background=\"#555555\">');
 | 
			
		||||
                        markup = markup.concat(GLib.utf8_substring(str,
 | 
			
		||||
                                                                   startIndex,
 | 
			
		||||
                                                                   endIndex));
 | 
			
		||||
                        markup = markup.concat('</span>');
 | 
			
		||||
                    }
 | 
			
		||||
                    if (endIndex < len) {
 | 
			
		||||
                        markup = markup.concat(GLib.utf8_substring(str,
 | 
			
		||||
                                                                   endIndex,
 | 
			
		||||
                                                                   len));
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                let clutter_text = this._stPreeditLabel.get_clutter_text();
 | 
			
		||||
                clutter_text.set_markup(markup);
 | 
			
		||||
                clutter_text.queue_redraw();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    showAuxiliaryText: function() {
 | 
			
		||||
        this._auxStringVisible = true;
 | 
			
		||||
        this._stAuxLabel.show();
 | 
			
		||||
        this._checkShowStates();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    hideAuxiliaryText: function() {
 | 
			
		||||
        this._auxStringVisible = false;
 | 
			
		||||
        this._checkShowStates();
 | 
			
		||||
        this._stAuxLabel.hide();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    updateAuxiliaryText: function(text, show) {
 | 
			
		||||
        if (show) {
 | 
			
		||||
            this.showAuxiliaryText();
 | 
			
		||||
        } else {
 | 
			
		||||
            this.hideAuxiliaryText();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._stAuxLabel.set_text(text.get_text());
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _refreshLabels: function() {
 | 
			
		||||
        let newLabels = [];
 | 
			
		||||
        for (let i = 0; this._lookupTable.get_label(i) != null; i++) {
 | 
			
		||||
            let label = this._lookupTable.get_label(i);
 | 
			
		||||
            newLabels.push([label.get_text(), label.get_attributes()]);
 | 
			
		||||
        }
 | 
			
		||||
        this._stCandidateArea.setLabels(newLabels);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    _getCandidatesInCurrentPage: function() {
 | 
			
		||||
        let cursorPos = this._lookupTable.get_cursor_pos();
 | 
			
		||||
        let pageSize = this._lookupTable.get_page_size();
 | 
			
		||||
        let page = ((cursorPos == 0) ? 0 : Math.floor(cursorPos / pageSize));
 | 
			
		||||
        let startIndex = page * pageSize;
 | 
			
		||||
        let endIndex = Math.min((page + 1) * pageSize,
 | 
			
		||||
                                this._lookupTable.get_number_of_candidates());
 | 
			
		||||
        let candidates = [];
 | 
			
		||||
        for (let i = startIndex; i < endIndex; i++) {
 | 
			
		||||
            candidates.push(this._lookupTable.get_candidate(i));
 | 
			
		||||
        }
 | 
			
		||||
        return candidates;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _getCursorPosInCurrentPage: function() {
 | 
			
		||||
        let cursorPos = this._lookupTable.get_cursor_pos();
 | 
			
		||||
        let pageSize = this._lookupTable.get_page_size();
 | 
			
		||||
        let posInPage = cursorPos % pageSize;
 | 
			
		||||
        return posInPage;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _refreshCandidates: function() {
 | 
			
		||||
        let candidates = this._getCandidatesInCurrentPage();
 | 
			
		||||
        let newCandidates = [];
 | 
			
		||||
        for (let i = 0; i < candidates.length; i++) {
 | 
			
		||||
            let candidate = candidates[i];
 | 
			
		||||
            newCandidates.push([candidate.get_text(),
 | 
			
		||||
                                candidate.get_attributes()]);
 | 
			
		||||
        }
 | 
			
		||||
        this._stCandidateArea.setCandidates(newCandidates,
 | 
			
		||||
                                            this._getCursorPosInCurrentPage(),
 | 
			
		||||
                                            this._lookupTable.is_cursor_visible());
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    updateLookupTable: function(lookupTable, visible) {
 | 
			
		||||
        // hide lookup table
 | 
			
		||||
        if (!visible) {
 | 
			
		||||
            this.hideLookupTable();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._lookupTable = lookupTable || new IBus.LookupTable();
 | 
			
		||||
        let orientation = this._lookupTable.get_orientation();
 | 
			
		||||
        if (orientation != ORIENTATION_HORIZONTAL &&
 | 
			
		||||
            orientation != ORIENTATION_VERTICAL) {
 | 
			
		||||
            orientation = this._orientation;
 | 
			
		||||
        }
 | 
			
		||||
        this.setCurrentOrientation(orientation);
 | 
			
		||||
        this._refreshCandidates();
 | 
			
		||||
        this._refreshLabels();
 | 
			
		||||
 | 
			
		||||
        // show lookup table
 | 
			
		||||
        if (visible) {
 | 
			
		||||
            this.showLookupTable();
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    showLookupTable: function() {
 | 
			
		||||
        this._lookupTableVisible = true;
 | 
			
		||||
        this._stCandidateArea.showAll();
 | 
			
		||||
        this._checkShowStates();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    hideLookupTable: function() {
 | 
			
		||||
        this._lookupTableVisible = false;
 | 
			
		||||
        this._checkShowStates();
 | 
			
		||||
        this._stCandidateArea.hideAll();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    pageUpLookupTable: function() {
 | 
			
		||||
        this._lookupTable.page_up();
 | 
			
		||||
        this._refreshCandidates();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    pageDownLookup_table: function() {
 | 
			
		||||
        this._lookupTable.page_down();
 | 
			
		||||
        this._refreshCandidates();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    cursorUpLookupTable: function() {
 | 
			
		||||
        this._lookupTable.cursor_up();
 | 
			
		||||
        this._refreshCandidates();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    cursorDownLookupTable: function() {
 | 
			
		||||
        this._lookupTable.cursor_down();
 | 
			
		||||
        this._refreshCandidates();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    setCursorLocation: function(x, y, w, h) {
 | 
			
		||||
        // if cursor location is changed, we reset the moved cursor location
 | 
			
		||||
        if (this._cursorLocation.join() != [x, y, w, h].join()) {
 | 
			
		||||
            this._cursorLocation = [x, y, w, h];
 | 
			
		||||
            this._movedCursorLocation = null;
 | 
			
		||||
            this._checkPosition();
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _checkShowStates: function() {
 | 
			
		||||
        this._checkSeparatorShowStates();
 | 
			
		||||
        if (this._preeditVisible ||
 | 
			
		||||
            this._auxStringVisible ||
 | 
			
		||||
            this._lookupTableVisible) {
 | 
			
		||||
            this._checkPosition();
 | 
			
		||||
            this.showAll();
 | 
			
		||||
            this.emit('show');
 | 
			
		||||
        } else {
 | 
			
		||||
            this.hideAll();
 | 
			
		||||
            this.emit('hide');
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _checkSeparatorShowStates: function() {
 | 
			
		||||
        if (this._preeditVisible || this._auxStringVisible) {
 | 
			
		||||
            this._separator.actor.show();
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
            this._separator.actor.hide();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    reset: function() {
 | 
			
		||||
        let text = IBus.Text.new_from_string('');
 | 
			
		||||
        this.updatePreeditText(text, 0, false);
 | 
			
		||||
        text = IBus.Text.new_from_string('');
 | 
			
		||||
        this.updateAuxiliaryText(text, false);
 | 
			
		||||
        this.updateLookupTable(null, false);
 | 
			
		||||
        this.hideAll();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    setCurrentOrientation: function(orientation) {
 | 
			
		||||
        if (this._currentOrientation == orientation) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        this._currentOrientation = orientation;
 | 
			
		||||
        this._stCandidateArea.setOrientation(orientation);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    setOrientation: function(orientation) {
 | 
			
		||||
        this._orientation = orientation;
 | 
			
		||||
        this.updateLookupTable(this._lookupTable, this._lookupTableVisible);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    getCurrentOrientation: function() {
 | 
			
		||||
        return this._currentOrientation;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _checkPosition: function() {
 | 
			
		||||
        let cursorLocation = this._movedCursorLocation || this._cursorLocation;
 | 
			
		||||
        let [cursorX, cursorY, cursorWidth, cursorHeight] = cursorLocation;
 | 
			
		||||
 | 
			
		||||
        let windowRight = cursorX + cursorWidth + this.actor.get_width();
 | 
			
		||||
        let windowBottom = cursorY + cursorHeight + this.actor.get_height();
 | 
			
		||||
 | 
			
		||||
        this._cursorActor.set_position(cursorX, cursorY);
 | 
			
		||||
        this._cursorActor.set_size(cursorWidth, cursorHeight);
 | 
			
		||||
 | 
			
		||||
        let monitor = Main.layoutManager.findMonitorForActor(this._cursorActor);
 | 
			
		||||
        let [sx, sy] = [monitor.x + monitor.width, monitor.y + monitor.height];
 | 
			
		||||
 | 
			
		||||
        if (windowBottom > sy) {
 | 
			
		||||
            this._arrowSide = St.Side.BOTTOM;
 | 
			
		||||
        } else {
 | 
			
		||||
            this._arrowSide = St.Side.TOP;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._boxPointer._arrowSide = this._arrowSide;
 | 
			
		||||
        this._boxPointer.setArrowOrigin(this._arrowSide);
 | 
			
		||||
        this._boxPointer.setPosition(this._cursorActor, this._arrowAlignment);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    showAll: function() {
 | 
			
		||||
        if (!this._isVisible) {
 | 
			
		||||
            this.actor.opacity = 255;
 | 
			
		||||
            this.actor.show();
 | 
			
		||||
            this._isVisible = true;
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    hideAll: function() {
 | 
			
		||||
        if (this._isVisible) {
 | 
			
		||||
            this.actor.opacity = 0;
 | 
			
		||||
            this.actor.hide();
 | 
			
		||||
            this._isVisible = false;
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    move: function(x, y) {
 | 
			
		||||
        this.actor.set_position(x, y);
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
Signals.addSignalMethods(CandidatePanel.prototype);
 | 
			
		||||
@@ -2,42 +2,52 @@
 | 
			
		||||
 | 
			
		||||
const Clutter = imports.gi.Clutter;
 | 
			
		||||
const GdkPixbuf = imports.gi.GdkPixbuf;
 | 
			
		||||
const Gkbd = imports.gi.Gkbd;
 | 
			
		||||
const Gio = imports.gi.Gio;
 | 
			
		||||
const GLib = imports.gi.GLib;
 | 
			
		||||
const Lang = imports.lang;
 | 
			
		||||
const Meta = imports.gi.Meta;
 | 
			
		||||
const Shell = imports.gi.Shell;
 | 
			
		||||
const St = imports.gi.St;
 | 
			
		||||
 | 
			
		||||
try {
 | 
			
		||||
    var IBus = imports.gi.IBus;
 | 
			
		||||
    const CandidatePanel = imports.ui.status.candidatePanel;
 | 
			
		||||
} catch (e) {
 | 
			
		||||
    var IBus = null;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const Main = imports.ui.main;
 | 
			
		||||
const PopupMenu = imports.ui.popupMenu;
 | 
			
		||||
const PanelMenu = imports.ui.panelMenu;
 | 
			
		||||
const Util = imports.misc.util;
 | 
			
		||||
 | 
			
		||||
const DESKTOP_INPUT_SOURCES_KEYBINDINGS_SCHEMA = 'org.gnome.desktop.input-sources.keybindings';
 | 
			
		||||
const DESKTOP_INPUT_SOURCES_SCHEMA = 'org.gnome.desktop.input-sources';
 | 
			
		||||
const KEY_CURRENT_IS    = 'current';
 | 
			
		||||
const KEY_INPUT_SOURCES = 'sources';
 | 
			
		||||
 | 
			
		||||
const LayoutMenuItem = new Lang.Class({
 | 
			
		||||
    Name: 'LayoutMenuItem',
 | 
			
		||||
    Extends: PopupMenu.PopupBaseMenuItem,
 | 
			
		||||
 | 
			
		||||
    _init: function(config, id, indicator, long_name) {
 | 
			
		||||
    _init: function(name, shortName, xkbLayout, xkbVariant, ibusEngine) {
 | 
			
		||||
        this.parent();
 | 
			
		||||
 | 
			
		||||
        this._config = config;
 | 
			
		||||
        this._id = id;
 | 
			
		||||
        this.label = new St.Label({ text: long_name });
 | 
			
		||||
        this.indicator = indicator;
 | 
			
		||||
        this.label = new St.Label({ text: name });
 | 
			
		||||
        this.indicator = new St.Label({ text: shortName });
 | 
			
		||||
        this.addActor(this.label);
 | 
			
		||||
        this.addActor(this.indicator);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    activate: function(event) {
 | 
			
		||||
        this.parent(event);
 | 
			
		||||
 | 
			
		||||
        this._config.lock_group(this._id);
 | 
			
		||||
        this.sourceName = name;
 | 
			
		||||
        this.shortName = shortName;
 | 
			
		||||
        this.xkbLayout = xkbLayout;
 | 
			
		||||
        this.xkbVariant = xkbVariant;
 | 
			
		||||
        this.ibusEngine = ibusEngine;
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const XKBIndicator = new Lang.Class({
 | 
			
		||||
    Name: 'XKBIndicator',
 | 
			
		||||
const InputSourceIndicator = new Lang.Class({
 | 
			
		||||
    Name: 'InputSourceIndicator',
 | 
			
		||||
    Extends: PanelMenu.Button,
 | 
			
		||||
 | 
			
		||||
    _init: function() {
 | 
			
		||||
@@ -50,61 +60,237 @@ const XKBIndicator = new Lang.Class({
 | 
			
		||||
        this.actor.add_actor(this._container);
 | 
			
		||||
        this.actor.add_style_class_name('panel-status-button');
 | 
			
		||||
 | 
			
		||||
        this._iconActor = new St.Icon({ icon_name: 'keyboard', icon_type: St.IconType.SYMBOLIC, style_class: 'system-status-icon' });
 | 
			
		||||
        this._container.add_actor(this._iconActor);
 | 
			
		||||
        this._labelActors = [ ];
 | 
			
		||||
        this._layoutItems = [ ];
 | 
			
		||||
 | 
			
		||||
        this._showFlags = false;
 | 
			
		||||
        this._config = Gkbd.Configuration.get();
 | 
			
		||||
        this._config.connect('changed', Lang.bind(this, this._syncConfig));
 | 
			
		||||
        this._config.connect('group-changed', Lang.bind(this, this._syncGroup));
 | 
			
		||||
        this._config.start_listen();
 | 
			
		||||
        this._settings = new Gio.Settings({ schema: DESKTOP_INPUT_SOURCES_SCHEMA });
 | 
			
		||||
        this._settings.connect('changed::' + KEY_CURRENT_IS, Lang.bind(this, this._currentISChanged));
 | 
			
		||||
        this._settings.connect('changed::' + KEY_INPUT_SOURCES, Lang.bind(this, this._inputSourcesChanged));
 | 
			
		||||
 | 
			
		||||
        this._syncConfig();
 | 
			
		||||
        if (IBus)
 | 
			
		||||
            this._ibusInit();
 | 
			
		||||
 | 
			
		||||
        this._inputSourcesChanged();
 | 
			
		||||
 | 
			
		||||
        if (global.session_type == Shell.SessionType.USER) {
 | 
			
		||||
            this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
 | 
			
		||||
            this.menu.addAction(_("Show Keyboard Layout"), Lang.bind(this, function() {
 | 
			
		||||
                Main.overview.hide();
 | 
			
		||||
                Util.spawn(['gkbd-keyboard-display', '-g', String(this._config.get_current_group() + 1)]);
 | 
			
		||||
                let description = this._selectedLayout.xkbLayout;
 | 
			
		||||
                if (this._selectedLayout.xkbVariant.length > 0)
 | 
			
		||||
                    description = description + '\t' + this._selectedLayout.xkbVariant;
 | 
			
		||||
                Util.spawn(['gkbd-keyboard-display', '-l', description]);
 | 
			
		||||
            }));
 | 
			
		||||
        }
 | 
			
		||||
        this.menu.addSettingsAction(_("Region and Language Settings"), 'gnome-region-panel.desktop');
 | 
			
		||||
 | 
			
		||||
        global.display.add_keybinding('switch-next',
 | 
			
		||||
                                      new Gio.Settings({ schema: DESKTOP_INPUT_SOURCES_KEYBINDINGS_SCHEMA }),
 | 
			
		||||
                                      Meta.KeyBindingFlags.NONE,
 | 
			
		||||
                                      Lang.bind(this, this._switchNext));
 | 
			
		||||
        global.display.add_keybinding('switch-previous',
 | 
			
		||||
                                      new Gio.Settings({ schema: DESKTOP_INPUT_SOURCES_KEYBINDINGS_SCHEMA }),
 | 
			
		||||
                                      Meta.KeyBindingFlags.NONE,
 | 
			
		||||
                                      Lang.bind(this, this._switchPrevious));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _adjustGroupNames: function(names) {
 | 
			
		||||
        // Disambiguate duplicate names with a subscript
 | 
			
		||||
        // This is O(N^2) to avoid sorting names
 | 
			
		||||
        // but N <= 4 so who cares?
 | 
			
		||||
    _ibusInit: function() {
 | 
			
		||||
        IBus.init();
 | 
			
		||||
        this._ibus = new IBus.Bus();
 | 
			
		||||
        if (!this._ibus.is_connected()) {
 | 
			
		||||
            log('ibus-daemon is not running');
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        for (let i = 0; i < names.length; i++) {
 | 
			
		||||
            let name = names[i];
 | 
			
		||||
            let cnt = 0;
 | 
			
		||||
            for (let j = i + 1; j < names.length; j++) {
 | 
			
		||||
                if (names[j] == name) {
 | 
			
		||||
                    cnt++;
 | 
			
		||||
                    // U+2081 SUBSCRIPT ONE
 | 
			
		||||
                    names[j] = name + String.fromCharCode(0x2081 + cnt);
 | 
			
		||||
                }
 | 
			
		||||
        this._ibus.request_name(IBus.SERVICE_PANEL,
 | 
			
		||||
                                IBus.BusNameFlag.ALLOW_REPLACEMENT |
 | 
			
		||||
                                IBus.BusNameFlag.REPLACE_EXISTING);
 | 
			
		||||
        this._panel = new IBus.PanelService({ connection: this._ibus.get_connection(),
 | 
			
		||||
                                              object_path: IBus.PATH_PANEL });
 | 
			
		||||
        this._ibusInitPanelService();
 | 
			
		||||
 | 
			
		||||
        this._candidatePanel = new CandidatePanel.CandidatePanel();
 | 
			
		||||
        this._ibusInitCandidatePanel();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _ibusInitCandidatePanel: function() {
 | 
			
		||||
        this._candidatePanel.connect('cursor-up',
 | 
			
		||||
                                     Lang.bind(this, function(widget) {
 | 
			
		||||
                                         this.cursorUp();
 | 
			
		||||
                                     }));
 | 
			
		||||
        this._candidatePanel.connect('cursor-down',
 | 
			
		||||
                                     Lang.bind(this, function(widget) {
 | 
			
		||||
                                         this.cursorDown();
 | 
			
		||||
                                     }));
 | 
			
		||||
        this._candidatePanel.connect('page-up',
 | 
			
		||||
                                     Lang.bind(this, function(widget) {
 | 
			
		||||
                                         this.pageUp();
 | 
			
		||||
                                     }));
 | 
			
		||||
        this._candidatePanel.connect('page-down',
 | 
			
		||||
                                     Lang.bind(this, function(widget) {
 | 
			
		||||
                                         this.pageDown();
 | 
			
		||||
                                     }));
 | 
			
		||||
        this._candidatePanel.connect('candidate-clicked',
 | 
			
		||||
                                     Lang.bind(this, function(widget, index, button, state) {
 | 
			
		||||
                                         this.candidateClicked(index, button, state);
 | 
			
		||||
                                     }));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _ibusInitPanelService: function() {
 | 
			
		||||
        this._panel.connect('set-cursor-location',
 | 
			
		||||
                            Lang.bind(this, this.setCursorLocation));
 | 
			
		||||
        this._panel.connect('update-preedit-text',
 | 
			
		||||
                            Lang.bind(this, this.updatePreeditText));
 | 
			
		||||
        this._panel.connect('show-preedit-text',
 | 
			
		||||
                            Lang.bind(this, this.showPreeditText));
 | 
			
		||||
        this._panel.connect('hide-preedit-text',
 | 
			
		||||
                            Lang.bind(this, this.hidePreeditText));
 | 
			
		||||
        this._panel.connect('update-auxiliary-text',
 | 
			
		||||
                            Lang.bind(this, this.updateAuxiliaryText));
 | 
			
		||||
        this._panel.connect('show-auxiliary-text',
 | 
			
		||||
                            Lang.bind(this, this.showAuxiliaryText));
 | 
			
		||||
        this._panel.connect('hide-auxiliary-text',
 | 
			
		||||
                            Lang.bind(this, this.hideAuxiliaryText));
 | 
			
		||||
        this._panel.connect('update-lookup-table',
 | 
			
		||||
                            Lang.bind(this, this.updateLookupTable));
 | 
			
		||||
        this._panel.connect('show-lookup-table',
 | 
			
		||||
                            Lang.bind(this, this.showLookupTable));
 | 
			
		||||
        this._panel.connect('hide-lookup-table',
 | 
			
		||||
                            Lang.bind(this, this.hideLookupTable));
 | 
			
		||||
        this._panel.connect('page-up-lookup-table',
 | 
			
		||||
                            Lang.bind(this, this.pageUpLookupTable));
 | 
			
		||||
        this._panel.connect('page-down-lookup-table',
 | 
			
		||||
                            Lang.bind(this, this.pageDownLookupTable));
 | 
			
		||||
        this._panel.connect('cursor-up-lookup-table',
 | 
			
		||||
                            Lang.bind(this, this.cursorUpLookupTable));
 | 
			
		||||
        this._panel.connect('cursor-down-lookup-table',
 | 
			
		||||
                            Lang.bind(this, this.cursorDownLookupTable));
 | 
			
		||||
        this._panel.connect('focus-in', Lang.bind(this, this.focusIn));
 | 
			
		||||
        this._panel.connect('focus-out', Lang.bind(this, this.focusOut));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    setCursorLocation: function(panel, x, y, w, h) {
 | 
			
		||||
        this._candidatePanel.setCursorLocation(x, y, w, h);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    updatePreeditText: function(panel, text, cursorPos, visible) {
 | 
			
		||||
        this._candidatePanel.updatePreeditText(text, cursorPos, visible);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    showPreeditText: function(panel) {
 | 
			
		||||
        this._candidatePanel.showPreeditText();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    hidePreeditText: function(panel) {
 | 
			
		||||
        this._candidatePanel.hidePreeditText();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    updateAuxiliaryText: function(panel, text, visible) {
 | 
			
		||||
        this._candidatePanel.updateAuxiliaryText(text, visible);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    showAuxiliaryText: function(panel) {
 | 
			
		||||
        this._candidatePanel.showAuxiliaryText();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    hideAuxiliaryText: function(panel) {
 | 
			
		||||
        this._candidatePanel.hideAuxiliaryText();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    updateLookupTable: function(panel, lookupTable, visible) {
 | 
			
		||||
        this._candidatePanel.updateLookupTable(lookupTable, visible);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    showLookupTable: function(panel) {
 | 
			
		||||
        this._candidatePanel.showLookupTable();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    hideLookupTable: function(panel) {
 | 
			
		||||
        this._candidatePanel.hideLookupTable();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    pageUpLookupTable: function(panel) {
 | 
			
		||||
        this._candidatePanel.pageUpLookupTable();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    pageDownLookupTable: function(panel) {
 | 
			
		||||
        this._candidatePanel.pageDownLookupTable();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    cursorUpLookupTable: function(panel) {
 | 
			
		||||
        this._candidatePanel.cursorUpLookupTable();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    cursorDownLookupTable: function(panel) {
 | 
			
		||||
        this._candidatePanel.cursorDownLookupTable();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    focusIn: function(panel, path) {
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    focusOut: function(panel, path) {
 | 
			
		||||
        this._candidatePanel.reset();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    cursorUp: function() {
 | 
			
		||||
        this._panel.cursor_up();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    cursorDown: function() {
 | 
			
		||||
        this._panel.cursor_down();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    pageUp: function() {
 | 
			
		||||
        this._panel.page_up();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    pageDown: function() {
 | 
			
		||||
        this._panel.page_down();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    candidateClicked: function(index, button, state) {
 | 
			
		||||
        this._panel.candidate_clicked(index, button, state);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _currentISChanged: function() {
 | 
			
		||||
        let source = this._settings.get_value(KEY_CURRENT_IS);
 | 
			
		||||
        let name = source.get_child_value(0).get_string()[0];
 | 
			
		||||
 | 
			
		||||
        if (this._selectedLayout) {
 | 
			
		||||
            this._selectedLayout.setShowDot(false);
 | 
			
		||||
            this._selectedLayout = null;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (this._selectedLabel) {
 | 
			
		||||
            this._container.set_skip_paint(this._selectedLabel, true);
 | 
			
		||||
            this._selectedLabel = null;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        for (let i = 0; i < this._layoutItems.length; ++i) {
 | 
			
		||||
            let item = this._layoutItems[i];
 | 
			
		||||
            if (item.sourceName == name) {
 | 
			
		||||
                item.setShowDot(true);
 | 
			
		||||
                this._selectedLayout = item;
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            if (cnt != 0)
 | 
			
		||||
                names[i] = name + '\u2081';
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return names;
 | 
			
		||||
        for (let i = 0; i < this._labelActors.length; ++i) {
 | 
			
		||||
            let actor = this._labelActors[i];
 | 
			
		||||
            if (actor.sourceName == name) {
 | 
			
		||||
                this._selectedLabel = actor;
 | 
			
		||||
                this._container.set_skip_paint(actor, false);
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (!this._selectedLayout || !this._selectedLabel)
 | 
			
		||||
            this._layoutItems[0].activate();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _syncConfig: function() {
 | 
			
		||||
        this._showFlags = this._config.if_flags_shown();
 | 
			
		||||
        if (this._showFlags) {
 | 
			
		||||
            this._container.set_skip_paint(this._iconActor, false);
 | 
			
		||||
        } else {
 | 
			
		||||
            this._container.set_skip_paint(this._iconActor, true);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let groups = this._config.get_group_names();
 | 
			
		||||
        if (groups.length > 1) {
 | 
			
		||||
    _inputSourcesChanged: function() {
 | 
			
		||||
        let sources = this._settings.get_value(KEY_INPUT_SOURCES);
 | 
			
		||||
        if (sources.n_children() > 1) {
 | 
			
		||||
            this.actor.show();
 | 
			
		||||
        } else {
 | 
			
		||||
            this.menu.close();
 | 
			
		||||
@@ -117,55 +303,69 @@ const XKBIndicator = new Lang.Class({
 | 
			
		||||
        for (let i = 0; i < this._labelActors.length; i++)
 | 
			
		||||
            this._labelActors[i].destroy();
 | 
			
		||||
 | 
			
		||||
        let short_names = this._adjustGroupNames(this._config.get_short_group_names());
 | 
			
		||||
 | 
			
		||||
        this._selectedLayout = null;
 | 
			
		||||
        this._layoutItems = [ ];
 | 
			
		||||
        this._selectedLabel = null;
 | 
			
		||||
        this._labelActors = [ ];
 | 
			
		||||
        for (let i = 0; i < groups.length; i++) {
 | 
			
		||||
            let icon_name = this._config.get_group_name(i);
 | 
			
		||||
            let actor;
 | 
			
		||||
            if (this._showFlags)
 | 
			
		||||
                actor = new St.Icon({ icon_name: icon_name, icon_type: St.IconType.SYMBOLIC, style_class: 'popup-menu-icon' });
 | 
			
		||||
            else
 | 
			
		||||
                actor = new St.Label({ text: short_names[i] });
 | 
			
		||||
            let item = new LayoutMenuItem(this._config, i, actor, groups[i]);
 | 
			
		||||
            item._short_group_name = short_names[i];
 | 
			
		||||
            item._icon_name = icon_name;
 | 
			
		||||
 | 
			
		||||
        for (let i = 0; i < sources.n_children(); ++i) {
 | 
			
		||||
            let name = sources.get_child_value(i).get_child_value(0).get_string()[0];
 | 
			
		||||
            let shortName = sources.get_child_value(i).get_child_value(1).get_string()[0];
 | 
			
		||||
            let xkbLayout = sources.get_child_value(i).get_child_value(2).get_string()[0];
 | 
			
		||||
            let xkbVariant = sources.get_child_value(i).get_child_value(3).get_string()[0];
 | 
			
		||||
            let ibusEngine = sources.get_child_value(i).get_child_value(4).get_string()[0];
 | 
			
		||||
 | 
			
		||||
            let item = new LayoutMenuItem(name, shortName, xkbLayout, xkbVariant, ibusEngine);
 | 
			
		||||
            this._layoutItems.push(item);
 | 
			
		||||
            this.menu.addMenuItem(item, i);
 | 
			
		||||
            item.connect('activate', Lang.bind(this, function() {
 | 
			
		||||
                if (this._selectedLayout == null || item.sourceName != this._selectedLayout.sourceName) {
 | 
			
		||||
                    let name = GLib.Variant.new_string(item.sourceName);
 | 
			
		||||
                    let shortName = GLib.Variant.new_string(item.shortName);
 | 
			
		||||
                    let xkbLayout = GLib.Variant.new_string(item.xkbLayout);
 | 
			
		||||
                    let xkbVariant = GLib.Variant.new_string(item.xkbVariant);
 | 
			
		||||
                    let ibusEngine = GLib.Variant.new_string(item.ibusEngine);
 | 
			
		||||
                    let tuple = GLib.Variant.new_tuple([name, shortName, xkbLayout, xkbVariant, ibusEngine], 5);
 | 
			
		||||
                    this._settings.set_value(KEY_CURRENT_IS, tuple);
 | 
			
		||||
                }
 | 
			
		||||
            }));
 | 
			
		||||
 | 
			
		||||
            let shortLabel = new St.Label({ text: short_names[i] });
 | 
			
		||||
            let shortLabel = new St.Label({ text: shortName });
 | 
			
		||||
            shortLabel.sourceName = name;
 | 
			
		||||
            this._labelActors.push(shortLabel);
 | 
			
		||||
            this._container.add_actor(shortLabel);
 | 
			
		||||
            this._container.set_skip_paint(shortLabel, true);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._syncGroup();
 | 
			
		||||
        this._currentISChanged();
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _syncGroup: function() {
 | 
			
		||||
        let selected = this._config.get_current_group();
 | 
			
		||||
 | 
			
		||||
        if (this._selectedLayout) {
 | 
			
		||||
            this._selectedLayout.setShowDot(false);
 | 
			
		||||
            this._selectedLayout = null;
 | 
			
		||||
    _switchNext: function() {
 | 
			
		||||
        if (!this._selectedLayout || !this._selectedLabel) {
 | 
			
		||||
            this._layoutItems[0].activate();
 | 
			
		||||
            return;
 | 
			
		||||
          }
 | 
			
		||||
        for (let i = 0; i < this._layoutItems.length; ++i) {
 | 
			
		||||
            let item = this._layoutItems[i];
 | 
			
		||||
            if (item.sourceName == this._selectedLayout.sourceName) {
 | 
			
		||||
                this._layoutItems[(++i == this._layoutItems.length) ? 0 : i].activate();
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
        if (this._selectedLabel) {
 | 
			
		||||
            this._container.set_skip_paint(this._selectedLabel, true);
 | 
			
		||||
            this._selectedLabel = null;
 | 
			
		||||
    _switchPrevious: function() {
 | 
			
		||||
        if (!this._selectedLayout || !this._selectedLabel) {
 | 
			
		||||
            this._layoutItems[0].activate();
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        for (let i = 0; i < this._layoutItems.length; ++i) {
 | 
			
		||||
            let item = this._layoutItems[i];
 | 
			
		||||
            if (item.sourceName == this._selectedLayout.sourceName) {
 | 
			
		||||
                this._layoutItems[(--i == -1) ? (this._layoutItems.length - 1) : i].activate();
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let item = this._layoutItems[selected];
 | 
			
		||||
        item.setShowDot(true);
 | 
			
		||||
 | 
			
		||||
        this._iconActor.icon_name = item._icon_name;
 | 
			
		||||
        this._selectedLabel = this._labelActors[selected];
 | 
			
		||||
        this._container.set_skip_paint(this._selectedLabel, this._showFlags);
 | 
			
		||||
 | 
			
		||||
        this._selectedLayout = item;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    _containerGetPreferredWidth: function(container, for_height, alloc) {
 | 
			
		||||
@@ -173,15 +373,11 @@ const XKBIndicator = new Lang.Class({
 | 
			
		||||
        // for the height of all children, but we ignore the results
 | 
			
		||||
        // for those we don't actually display.
 | 
			
		||||
        let max_min_width = 0, max_natural_width = 0;
 | 
			
		||||
        if (this._showFlags)
 | 
			
		||||
            [max_min_width, max_natural_width] = this._iconActor.get_preferred_width(for_height);
 | 
			
		||||
 | 
			
		||||
        for (let i = 0; i < this._labelActors.length; i++) {
 | 
			
		||||
            let [min_width, natural_width] = this._labelActors[i].get_preferred_width(for_height);
 | 
			
		||||
            if (!this._showFlags) {
 | 
			
		||||
                max_min_width = Math.max(max_min_width, min_width);
 | 
			
		||||
                max_natural_width = Math.max(max_natural_width, natural_width);
 | 
			
		||||
            }
 | 
			
		||||
            max_min_width = Math.max(max_min_width, min_width);
 | 
			
		||||
            max_natural_width = Math.max(max_natural_width, natural_width);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        alloc.min_size = max_min_width;
 | 
			
		||||
@@ -190,15 +386,11 @@ const XKBIndicator = new Lang.Class({
 | 
			
		||||
 | 
			
		||||
    _containerGetPreferredHeight: function(container, for_width, alloc) {
 | 
			
		||||
        let max_min_height = 0, max_natural_height = 0;
 | 
			
		||||
        if (this._showFlags)
 | 
			
		||||
            [max_min_height, max_natural_height] = this._iconActor.get_preferred_height(for_width);
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        for (let i = 0; i < this._labelActors.length; i++) {
 | 
			
		||||
            let [min_height, natural_height] = this._labelActors[i].get_preferred_height(for_width);
 | 
			
		||||
            if (!this._showFlags) {
 | 
			
		||||
                max_min_height = Math.max(max_min_height, min_height);
 | 
			
		||||
                max_natural_height = Math.max(max_natural_height, natural_height);
 | 
			
		||||
            }
 | 
			
		||||
            max_min_height = Math.max(max_min_height, min_height);
 | 
			
		||||
            max_natural_height = Math.max(max_natural_height, natural_height);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        alloc.min_size = max_min_height;
 | 
			
		||||
@@ -212,7 +404,6 @@ const XKBIndicator = new Lang.Class({
 | 
			
		||||
        box.y2 -= box.y1;
 | 
			
		||||
        box.y1 = 0;
 | 
			
		||||
 | 
			
		||||
        this._iconActor.allocate_align_fill(box, 0.5, 0, false, false, flags);
 | 
			
		||||
        for (let i = 0; i < this._labelActors.length; i++)
 | 
			
		||||
            this._labelActors[i].allocate_align_fill(box, 0.5, 0, false, false, flags);
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user