Traduzca

Translate to EnglishÜbersetzen Sie zum Deutsch/GermanΜεταφράστε στα ελληνικά/GreekПереведите к русскому/RussianOversetter til Norsk/NorwegianÖversätta till Svensk/Swedishहिनà¥à¤¦à¥€ अनà¥à¤µà¤¾à¤¦ करने के लिà¤/Hindi
Tradueix al català/CatalanTulkot uz latviešu/LatvianPreložiť do slovenčiny/SlovakVertaal aan het Nederlands/Dutchترجمة الى العربية/ArabicTraduzca al Español/SpanishTraduisez au Français/French
Traduca ad Italiano/ItalianTraduza ao Português/Portuguese日本語に翻訳しなさい /Japanese한국어에게 번역하십시오/Korean中文翻译/Chinese Simplified中文翻译/Chinese TraditionalПереклад на українську/Ukrainian
La imagen de RHCE Red Hat certificó la guía del estudio del linux del ingeniero (examen RH302) (la prensa de la certificación)
Imagen de los conceptos del sistema operativo
Imagen de comenzar Google Maps API 3
Imagen del desarrollo del núcleo del linux (3ro edición)

Menús duales para un botón de Shell 3.2 del GNOMO

Una de las limitaciones actuales con los botones del panel superior de Shell del GNOMO 3.2 es que no hay ayuda para exhibir los menús separados para diversos tecleos del botón de ratón. Sí, sí, puedo oír que los diseñadores de Shell del GNOMO dicen con autoridad y la convicción completas que este caso del uso está por diseño. Su respuesta a cualquier crítica, constructiva o de otra manera, sobre su diseño es generalmente que saben mejor que cualquiera y sus estudios (nunca-publicados) de la utilidad apoyan su diseño. ¡Apenas mire el discusión de la opción del menú de la energía del versa del suspender apagado que entró en erupción cuando el GNOMO Shell fue lanzado originalmente!

De todas formas, esta limitación particular me ha molestado que durante algún tiempo y decidía recientemente mirar la edición e intentar y subir con una solución realizable simple a la limitación.

Suponga que quisiera que el menú siguiente fuera exhibido cuando utilizo mi botón de ratón izquierdo para activar el botón del pie del GNOMO en el panel superior:

y quisiera que las opciones siguientes del menú fueran exhibidas cuando utilizo mi botón de ratón derecho para activar el mismo botón del panel superior:

No hay nada en ser la base murmura el código que los límites apoyan para tal funcionalidad. De hecho murmure tiene ayuda explícita para volver un número entero que represente un botón de ratón presionado o lanzado. Según la documentación del alboroto (sobre cuáles murmuran se basa), en el caso de un ratón estándar de la voluta, los números siguientes son confiables:

  • 1 = botón de ratón izquierdo
  • 2 = rueda de la voluta
  • 3 = botón de ratón derecho

Para los ratones con más botones, usted puede tener que experimentar para ver qué botón particular vuelve que valor particular.

¿En su código, cómo usted determina qué botón de ratón particular fue presionado? Conecte simplemente un tratante de acontecimiento (los tratantes del servicio repetido o de la señal de AKA) con el botón-presionar-acontecimiento y/o las señales del botón-lanzar-acontecimiento de un agente conveniente. En el tratante de acontecimiento, get_button del uso () para volver el número entero que representa el botón de ratón específico que fue presionado y/o lanzado. Usted puede utilizar una sola función para las señales de la prensa y del lanzamiento.

   ...

   _init: function(menuAlignment) {
        PanelMenu.ButtonBox.prototype._init.call(this,
                                                 { reactive: true,
                                                   can_focus: true,
                                                   track_hover: true
                                                 });
        ...
        this.actor.connect('button-press-event', Lang.bind(this, this._onButtonPress));
        ...
    },

    _onButtonPress: function(actor, event) {
        let button = event.get_button();
        if (button == 1) {
            // do something
        } else if (button == 3) {
            // do something
        }
    },

    ...


Se emite cuando se presiona un botón de ratón, pero se lanza no no necesariamente un botón-presionar-acontecimiento, en un agente reactivo. Se emite un botón-lanzar-acontecimiento cuando un botón de ratón se lanza en un agente reactivo (incluso si el ratón fue apretado en alguna parte de antemano). Usted debe permitir generalmente explícitamente la característica reactiva de un agente. A propósito, un agente reactivo (un concepto del alboroto) es un agente que puede emitir acontecimientos del indicador.

Un acercamiento alternativo es utilizar Clutter.ClickAction.


   ...

   let clickAction = new Clutter.ClickAction();
   clickAction.connect('clicked', Lang.bind(this, function(button)  {
       this._onButtonPress(button);
   }));
   this.actor.add_action(clickAction);

   ...

    _onButtonPress: function(button) {
        if (button == 1) {
            // do something
        } else if (button == 3) {
            // do something
        }
    },

    ...


Por ejemplos de cómo y donde Clutter.ClickAction se utiliza en el código de Shell 3.2 del GNOMO, la mirada en /usr/share/gnome-shell/js/ui/shellEntry.js y /usr/share/gnome-shell/js/ui/workspace.js donde se utiliza al instrumento chascado y largo-presione la dirección del acontecimiento.

De nuevo al problema actual. Resulta que el impedimiento principal a ejecutar de menús duales de la acción en el GNOMO Shell 3.2 miente en el código que ejecuta el objeto del botón. Vea /usr/share/gnome-shell/js/ui/panelMenu.js. Aquí está el código relevante:

function Button(menuAlignment) {
    this._init(menuAlignment);
}

Button.prototype = {
    __proto__: ButtonBox.prototype,

    _init: function(menuAlignment) {
        ButtonBox.prototype._init.call(this, { reactive: true,
                                               can_focus: true,
                                               track_hover: true });

        this.actor.connect('button-press-event', Lang.bind(this, this._onButtonPress));
        this.actor.connect('key-press-event', Lang.bind(this, this._onSourceKeyPress));
        this.menu = new PopupMenu.PopupMenu(this.actor, menuAlignment, St.Side.TOP);
        this.menu.actor.add_style_class_name('panel-menu');
        this.menu.connect('open-state-changed', Lang.bind(this, this._onOpenStateChanged));
        this.menu.actor.connect('key-press-event', Lang.bind(this, this._onMenuKeyPress));
        Main.uiGroup.add_actor(this.menu.actor);
        this.menu.actor.hide();
    },

function Button(menuAlignment) {
    this._init(menuAlignment);
}

Button.prototype = {
    __proto__: ButtonBox.prototype,

    _init: function(menuAlignment) {
        ButtonBox.prototype._init.call(this, { reactive: true,
                                               can_focus: true,
                                               track_hover: true });

        this.actor.connect('button-press-event', Lang.bind(this, this._onButtonPress));
        this.actor.connect('key-press-event', Lang.bind(this, this._onSourceKeyPress));
        this.menu = new PopupMenu.PopupMenu(this.actor, menuAlignment, St.Side.TOP);
        this.menu.actor.add_style_class_name('panel-menu');
        this.menu.connect('open-state-changed', Lang.bind(this, this._onOpenStateChanged));
        this.menu.actor.connect('key-press-event', Lang.bind(this, this._onMenuKeyPress));
        Main.uiGroup.add_actor(this.menu.actor);
        this.menu.actor.hide();
    },

   _onButtonPress: function(actor, event) {
        if (!this.menu.isOpen) {
            // Setting the max-height won't do any good if the minimum height of the
            // menu is higher then the screen; it's useful if part of the menu is
            // scrollable so the minimum height is smaller than the natural height
            let monitor = Main.layoutManager.primaryMonitor;
            this.menu.actor.style = ('max-height: ' +
                                     Math.round(monitor.height - Main.panel.actor.height) +
                                     'px;');
        }
        this.menu.toggle();
    },

    _onSourceKeyPress: function(actor, event) {
        let symbol = event.get_key_symbol();
        if (symbol == Clutter.KEY_space || symbol == Clutter.KEY_Return) {
            this.menu.toggle();
            return true;
        } else if (symbol == Clutter.KEY_Escape && this.menu.isOpen) {
            this.menu.close();
            return true;
        } else if (symbol == Clutter.KEY_Down) {
            if (!this.menu.isOpen)
                this.menu.toggle();
            this.menu.actor.navigate_focus(this.actor, Gtk.DirectionType.DOWN, false);
            return true;
        } else
            return false;
    },

   _onMenuKeyPress: function(actor, event) {
        let symbol = event.get_key_symbol();
        if (symbol == Clutter.KEY_Left || symbol == Clutter.KEY_Right) {
            let focusManager = St.FocusManager.get_for_stage(global.stage);
            let group = focusManager.get_group(this.actor);
            if (group) {
                let direction = (symbol == Clutter.KEY_Left) ? Gtk.DirectionType.LEFT : Gtk.DirectionType.RIGHT;
                group.navigate_focus(this.actor, direction, false);
                return true;
            }
        }
        return false;
    },

    _onOpenStateChanged: function(menu, open) {
        if (open)
            this.actor.add_style_pseudo_class('active');
        else
            this.actor.remove_style_pseudo_class('active');
    },

    destroy: function() {
        this.actor._delegate = null;

        this.menu.destroy();
        this.actor.destroy();

        this.emit('destroy');
    }
};
Signals.addSignalMethods(Button.prototype);


Si usted examina el código antedicho, usted verá que no se hace ninguna tentativa de distinguir entre los diversos botones de ratón. Por lo que el código antedicho, un botón de ratón es igual que otro botón de ratón. Quizás los diseñadores del GNOMO Shell crecieron usando un solo ratón o, tantos comentaristas han sugerido, el GNOMO Shell de Apple del botón fue diseñado realmente para las tabletas y los palmhelds donde no hay utilizado generalmente o disponible ratón.

La solución a ejecutar de funcionalidad dual del menú usando los botones de ratón era modificar al tratante de la señal del buttom-presionar-acontecimiento en el código antedicho del botón para determinar qué botón de ratón fue presionado y acto por consiguiente.

Aquí está el código fuente para una extensión simple de Shell del GNOMO que utilicé al prototipo una puesta en práctica de trabajo de la funcionalidad dual del menú:

const St = imports.gi.St;
const Main = imports.ui.main;
const PanelMenu = imports.ui.panelMenu;
const PopupMenu = imports.ui.popupMenu;
const Lang = imports.lang;

const Clutter = imports.gi.Clutter;
const Shell = imports.gi.Shell;
const Signals = imports.signals;

function DualActionButton(menuAlignment) {
    this._init(menuAlignment);
}

DualActionButton.prototype = {
    __proto__: PanelMenu.ButtonBox.prototype,

    _init: function(menuAlignment) {
        PanelMenu.ButtonBox.prototype._init.call(this, { reactive: true,
                                               can_focus: true,
                                               track_hover: true });

        this.actor.connect('button-press-event', Lang.bind(this, this._onButtonPress));
        this.actor.connect('key-press-event', Lang.bind(this, this._onSourceKeyPress));

        this.menuL = new PopupMenu.PopupMenu(this.actor, menuAlignment, St.Side.TOP);
        this.menuL.actor.add_style_class_name('panel-menu');
        this.menuL.connect('open-state-changed', Lang.bind(this, this._onOpenStateChanged));
        this.menuL.actor.connect('key-press-event', Lang.bind(this, this._onMenuKeyPress));
        Main.uiGroup.add_actor(this.menuL.actor);
        this.menuL.actor.hide();

        this.menuR = new PopupMenu.PopupMenu(this.actor, menuAlignment, St.Side.TOP);
        this.menuR.actor.add_style_class_name('panel-menu');
        this.menuR.connect('open-state-changed', Lang.bind(this, this._onOpenStateChanged));
        this.menuR.actor.connect('key-press-event', Lang.bind(this, this._onMenuKeyPress));
        Main.uiGroup.add_actor(this.menuR.actor);
        this.menuR.actor.hide();
    },

    _onButtonPress: function(actor, event) {
        let button = event.get_button();
        if (button == 1) {
            if (this.menuL.isOpen) {
                this.menuL.close();
            } else {
                if (this.menuR.isOpen)
                    this.menuR.close();
                this.menuL.open();
            }
        } else if (button == 3) {
            if (this.menuR.isOpen) {
                this.menuR.close();
            } else {
                if (this.menuL.isOpen)
                    this.menuL.close();
                this.menuR.open();
            }
        }
    },

    _onButtonPress: function(actor, event) {
        let button = event.get_button();
        if (button == 1) {
            if (this.menuL.isOpen) {
                this.menuL.close();
            } else {
                if (this.menuR.isOpen)
                    this.menuR.close();
                this.menuL.open();
            }
        } else if (button == 3) {
            if (this.menuR.isOpen) {
                this.menuR.close();
            } else {
                if (this.menuL.isOpen)
                    this.menuL.close();
                this.menuR.open();
            }
        }
    },

    _onSourceKeyPress: function(actor, event) {
        let symbol = event.get_key_symbol();
        if (symbol == Clutter.KEY_space || symbol == Clutter.KEY_Return) {
            if (this.menuL.isOpen) {
                this.menuL.close();
            } else if (this.menuR.isOpen) {
                this.menuR.close();
            }
            return true;
        } else if (symbol == Clutter.KEY_Escape) {
            if (this.menuL.isOpen)
                this.menuL.close();
            if (this.menuR.isOpen)
                this.menuR.close();
            return true;
        } else
            return false;
    },

    _onMenuKeyPress: function(actor, event) {
        let symbol = event.get_key_symbol();
        if (symbol == Clutter.KEY_Left || symbol == Clutter.KEY_Right) {
            let focusManager = St.FocusManager.get_for_stage(global.stage);
            let group = focusManager.get_group(this.actor);
            if (group) {
                let direction = (symbol == Clutter.KEY_Left) ? Gtk.DirectionType.LEFT : Gtk.DirectionType.RIGHT;
                group.navigate_focus(this.actor, direction, false);
                return true;
            }
        }
        return false;
    },

    _onOpenStateChanged: function(menu, open) {
        if (open)
            this.actor.add_style_pseudo_class('active');
        else
            this.actor.remove_style_pseudo_class('active');
    },

    destroy: function() {
        this.actor._delegate = null;
        this.menuL.destroy();
        this.menuR.destroy();
        this.actor.destroy();
        this.emit('destroy');
    },

};
Signals.addSignalMethods(DualActionButton.prototype);

function DemoDualActionButton() {
   this._init();
}

DemoDualActionButton.prototype = {
    __proto__: DualActionButton.prototype,

    _init: function() {
        DualActionButton.prototype._init.call(this, 0.0);

        this._iconActor = new St.Icon({ icon_name: 'start-here',
                                        icon_type: St.IconType.SYMBOLIC,
                                        style_class: 'system-status-icon' });
        this.actor.add_actor(this._iconActor);
        this.actor.add_style_class_name('panel-status-button');

        let item = new PopupMenu.PopupMenuItem(_("Left Menu Item 1"));
        this.menuL.addMenuItem(item);
        item = new PopupMenu.PopupMenuItem(_("Left Menu Item 2"));
        this.menuL.addMenuItem(item);

        item = new PopupMenu.PopupMenuItem(_("Right Menu Item 1"));
        this.menuR.addMenuItem(item);
        item = new PopupMenu.PopupMenuItem(_("Right Menu Item 2"));
        this.menuR.addMenuItem(item);
        item = new PopupMenu.PopupMenuItem(_("Right Menu Item 3"));
        this.menuR.addMenuItem(item);
        item = new PopupMenu.PopupMenuItem(_("Right Menu Item 4"));
        this.menuR.addMenuItem(item);
    },

    enable: function() {
        Main.panel._centerBox.add(this.actor, { y_fill: true });
        Main.panel._menus.addMenu(this.menuL);
        Main.panel._menus.addMenu(this.menuR);
    },

    disable: function() {
        Main.panel._centerBox.remove_actor(this.actor);
        Main.panel._menus.removeMenu(this.menuL);
        Main.panel._menus.removeMenu(this.menuR);
    }
};

function init() {
    return new DemoDualActionButton();
}


El código de objeto de DualActionButton es simplemente una versión modificada del código del botón. El adición de la ayuda para un menú de centro del botón de ratón es trivial; Dejaré eso para que usted haga si usted lo necesita.

Observe que no incluyo una coma después de los pares del apellido/del valor. Según la documentación del Javascript de Mozilla, Douglas Crockford y otras, ésta es el sintaxis correcto. Desafortunadamente, muchos reveladores de las extensiones de Shell aparecen no saber el sintaxis correcto para los literales del objeto e incluir la coma desde gjs, que se basa en el motor del Javascript de Mozilla SpiderMonkey y el marco de la introspección de GObject, no se queja por este error de sintaxis particular.

Para esos lectores que no tengan gusto de encapsular la extensión de Shell del GNOMO permita e inhabilite los métodos, y hay absolutamente algunos de usted según comentarios y el email que recibo, aquí es el código fuente para la inicialización basada función, permitir e inhabilitar de la extensión antedicha.

let button;

function init() {
    button = new DemoDualActionButton();
}

function enable() {
    Main.panel._centerBox.add(button.actor, { y_fill: true });
    Main.panel._menus.addMenu(button.menuL);
    Main.panel._menus.addMenu(button.menuR);
}

function disable() {
    Main.panel._centerBox.remove_actor(button.actor);
    Main.panel._menus.removeMenu(button.menuL);
    Main.panel._menus.removeMenu(button.menuR);
}


Alguna gente demanda que el código antedicho para manejar una extensión de Shell es más simple y más fácil entender que el estilo literal de la codificación del objeto que utilizo generalmente. Mi respuesta es que el acercamiento de la función le requiere utilizar por lo menos una variable que tenga alcance de la extensión y, a menudo épocas, muchas tales variables en extensiones más complejas de Shell. El Javascript actualmente no estándar de Mozilla dejó límites de la palabra clave el alcance léxico de una variable al bloque en el cual se define la variable tan bien como cualquier bloque interno contuvo el interior dejó el bloque sí mismo. Sin embargo, si la palabra clave del var se utiliza en vez de dejó palabra clave o no se utiliza ninguna palabra clave, el alcance de la variable omite global. Las variables globales en Javascript se deben evitar en lo posible debido a los efectos secundarios y los errores potenciales que pueden introducir. Este tipo de error del scoping puede ser difícil de encontrar y así que elijo evitar la edición enteramente. Lea el apéndice A (piezas tremendas) del Javascript seminal del libro de Douglas Crockford: Las buenas partes si usted no entiende porqué las variables del Javascript con alcance global son malvadas.

A propósito, no estoy seguro si el concepto de un botón dual del menú de la acción practicaría una abertura las pautas de la accesibilidad de la computadora (a11y) para el GNOMO Shell pero dado que el paradigma es común en Microsoft Windows, sospecho no.

He creado una extensión simple de Shell del GNOMO, demodualmenubutton, basado en el código antedicho que usted puede transferir de mi Web site de las extensiones de Shell del GNOMO.

¡Goce!

4 comentarios a doblarse menús para un botón de Shell 3.2 del GNOMO

  • Odio ser tan conciso. ¿Pero por qué usted está perdiendo su tiempo en todas estas extensiones (esas utilizo el diario a propósito)? Veo su nombre y este Web site a través de la red todo el tiempo - aprendo de las páginas que usted fija, pero sigue habiendo una pregunta: ¿Por qué usted no está llevando la codificación para el GNOMO?

    • Realmente, paso tiempo o energía muy pequeño en extensiones del GNOMO. No tenga simplemente el tiempo o la inclinación. En cuanto a llevar la codificación para el GNOMO, no va a suceder mientras que discrepo con el diseño y la filosofía de la ejecución del equipo de la base de Shell del GNOMO.

  • LONNIEFUTURE

    Era curioso sobre sus derechos reservados. ¿Los derechos reservados significan su trabajo no pueden ser redistribuidos? ¿Por qué derechos reservados FOSS?

    • La licencia y los derechos reservados son dos diversos conceptos que se confunden a menudo en el mundo de FOSS. Mi trabajo se puede redistribuir por el GLP le proporcionó licencia mi aviso de derechos reservados en él. Usted puede agregar su propio aviso de derechos reservados si usted modifica mi trabajo pero usted debe dejar mi aviso de derechos reservados en el lugar.

      En los E.E.U.U., y en la mayoría de los países, usted tiene automáticamente derechos reservados a cualquier trabajo publicado. Eso sucede por abandono tan pronto como se publique el trabajo. De hecho, usted tiene que poner su trabajo explícitamente en el public domain si usted no quisiera que el trabajo fuera con derechos de autor.

      Vea http://www.gnu.org/licenses/gpl-faq.html#RequiredToClaimCopyright para más información.

Deje una contestación