Übersetzen Sie

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
Bild der vorgerückten Programmierung in der UNIX-Umwelt, zweite Ausgabe (Wesley-Fachmann-rechnenreihen)
Bild von Betriebssystemkonzepten
Bild des Beginns von Google Maps API 3
Bild der Linux-Kern-Entwicklung (3. Ausgabe)

Doppelmenüs für einen Knopf GNOME Shell-3.2

Eine der gegenwärtigen Beschränkungen mit den GNOME 3.2 Shell-Spitzenverkleidungsknöpfen ist, dass es keine Unterstützung für das Anzeigen der unterschiedlichen Menüs für unterschiedliches Maustastenklicken gibt. Ja ja kann ich hören, dass die GNOME Shell-Entwerfer mit kompletter Berechtigung und Überzeugung sagen, dass dieser Gebrauchfall mit Absicht ist. Ihre Antwort zu jeder möglicher Kritik, konstruktiven oder anders, über ihren Entwurf ist im Allgemeinen, dass sie besser wissen, als jedes sonst und ihre (nie-erschienenen) Brauchbarkeitstudien ihren Entwurf stützen. Betrachten Sie einfach die Menüwahldebatte des verschieben versa Ausschaltens, die ausbrach, als der GNOME Shell ursprünglich freigegeben wurde!

Sowieso hat diese bestimmte Beschränkung mich gestört, dass für eine Weile und ich mich vor kurzem entschied, die Ausgabe zu betrachten und mit einer einfachen bearbeitbaren Lösung zur Beschränkung zu versuchen und aufzukommen.

Nehmen Sie an, dass ich das folgende Menü angezeigt werden wünschte, wenn ich meine linke Maustaste benutze, um den GNOME Fußknopf auf der Spitzenverkleidung zu aktivieren:

und ich wünsche die folgenden Menüwahlen angezeigt werden, wenn ich meine rechte Maustaste benutze, um den gleichen Spitzenverkleidungsknopf zu aktivieren:

Es gibt nichts im Zugrunde liegen murmeln Code, den Begrenzungen für solche Funktionalität stützen. Murmeln Sie tatsächlich hat ausdrückliche Unterstützung für das Zurückbringen einer ganzen Zahl, die eine gepresste oder freigegebene Maustaste darstellt. Entsprechend den Unterlagen der Unordnung (nach, welchen murmeln, basiert) im Falle einer Standardrollemaus, sind die folgenden Zahlen zuverlässig:

  • 1 = linke Maustaste
  • 2 = Rollerad
  • 3 = rechte Maustaste

Für Mäuse mit mehr Knöpfen, können Sie experimentieren müssen, um zu sehen, welcher bestimmte Knopf zurückgeht, der bestimmter Wert.

In Ihrem Code wie stellen Sie fest, welche bestimmte Maustaste betätigt wurde? Schließen Sie einfach eine Ereigniszufuhr (AKA Wiederholungsbesuchs- oder Signalzufuhren) an das Knopf-betätigenereignis und/oder die Knopf-freigebenereignis Signale eines verwendbaren Schauspielers an. Im Falle Zufuhr, Gebrauch get_button () zum der ganzen Zahl zurückzubringen, welche die spezifische Maustaste darstellt, die betätigt und/oder freigegeben wurde. Sie können eine einzelne Funktion für Presse- und Freigabesignale verwenden.

   ...

   _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
        }
    },

    ...


Ein Knopf-betätigenereignis wird, wenn eine Maustaste betätigt wird ausgestrahlt, aber freigegeben nicht notwendigerweise, auf einem reagierenden Schauspieler. Ein Knopf-freigebenereignis wird ausgestrahlt, wenn eine Maustaste auf einem reagierenden Schauspieler freigegeben wird (selbst wenn die Maus irgendwo sonst vorher heruntergedrückt wurde). Normalerweise müssen Sie dem reagierenden Eigentum eines Schauspielers ausdrücklich ermöglichen. Übrigens ist ein reagierender Schauspieler (ein Unordnungkonzept) ein Schauspieler, der Zeigerereignisse ausstrahlen kann.

Ein alternativer Ansatz ist, Clutter.ClickAction zu verwenden.


   ...

   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
        }
    },

    ...


Für Beispiele wie und wo Clutter.ClickAction im Code GNOME Shell-3.2, im Blick in /usr/share/gnome-shell/js/ui/shellEntry.js und in /usr/share/gnome-shell/js/ui/workspace.js verwendet wird, in dem es an das angeklickte Werkzeug gewöhnt ist und lang-betätigen Sie die Ereignisbehandlung.

Zurück zu dem Problem zur Hand. Es fällt aus, dass die Hauptbehinderung zur Implementierung der Doppeltätigkeitsmenüs im GNOME Shell 3.2 im Code liegt, der den Knopfgegenstand einführt. Sehen Sie /usr/share/gnome-shell/js/ui/panelMenu.js. Ist hier der relevante Code:

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);


Wenn Sie den oben genannten Code überprüfen, sehen Sie, dass kein Versuch, zwischen den verschiedenen Maustasten zu unterscheiden gebildet wird. Insoweit der oben genannte Code, ist eine Maustaste die selbe wie eine andere Maustaste. Möglicherweise wuchsen die Entwerfer des GNOME Shell unter Verwendung einer einzelnen Knopf Apple-Maus oder auf, da viele Kommentatoren haben vorgeschlagen, des GNOME Shell war wirklich für Tabletten und palmhelds bestimmt, in denen keine Maus im Allgemeinen verwendet oder vorhanden ist.

Die Lösung zur Implementierung der Doppelmenüfunktionalität unter Verwendung der Maustasten war, die Buttom-betätigenereignis Signalzufuhr im oben genannten Knopfcode zu ändern, um festzustellen, welche Maustaste und Tat dementsprechend betätigt wurde.

Ist hier der Quellencode für eine einfache GNOME Shell-Verlängerung, der ich zum Prototyp eine Arbeitsimplementierung der Doppelmenüfunktionalität verwendete:

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();
}


Der DualActionButton Objektcode ist einfach eine geänderte Version des Knopfcodes. Unterstützung für ein Mittelmaustastenmenü hinzuzufügen ist trivial; Ich lasse den, damit Sie tun, wenn Sie es benötigen.

Merken Sie, dass ich ein Komma nicht nach den Nachname-/Wertpaaren einschließe. Entsprechend den Mozilla Javascriptunterlagen ist Douglas Crockford und andere, dieses die korrekte Syntax. Leider scheinen viele Shell-Verlängerungsentwickler, die korrekte Syntax für Gegenstanddruckfehler nicht zu kennen und das Komma seit gjs einzuschließen, das auf der Mozilla SpiderMonkey Javascript maschine und dem GObject Selbstbeobachtung rahmen basiert, beschwert nicht sich über diese bestimmte Syntaxstörung.

Für jene Leser, die nicht die GNOME Shell-Verlängerung einkapseln mögen, ermöglichen Sie und sperren Sie Methoden, und es gibt durchaus einige von Ihnen entsprechend Anmerkungen und eMail, die ich empfange, ist hier der Quellencode für Funktion gegründete Initialisierung, das Ermöglichen und die Sperrung der oben genannten Verlängerung.

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);
}


Einige Leute behaupten, dass der oben genannte Code für die Behandlung einer Shell-Verlängerung einfacher und einfacher als die wörtliche Kodierungart des Gegenstandes zu verstehen ist, die ich im Allgemeinen verwende. Meine Antwort ist, dass die Funktionsannäherung Sie erfordert, mindestens eine Variable, die Verlängerungsbereich hat und, häufig Zeiten, viele solchen Variablen zu verwenden in den komplizierteren Shell-Verlängerungen. Das z.Z. nichtstandardisierte Mozilla Javascript ließ Schlüsselwortbegrenzungen der lexikalische Bereich einer Variable zum Block, in dem die Variable definiert wird, sowie alle inneren Blöcke enthielt das Innere ließ Block selbst. Jedoch wenn das var-Schlüsselwort anstelle von ließ Schlüsselwort verwendet wird, oder kein Schlüsselwort verwendet wird, führt der Bereich der Variable zu globalem. Globale Variablen im Javascript sollten wegen der möglichen Nebenwirkungen und der Störungen wo möglich vermieden werden, die sie einführen können. Diese Art der Scopingstörung kann schwierig sein zu finden und also beschließe ich, die Ausgabe völlig zu vermeiden. Lesen Sie Anhang A (schreckliche Teile) des fruchtbaren Buch Javascript Douglas- Crockfords: Die guten Teile, wenn Sie nicht verstehen, warum Javascriptvariablen mit globalem Bereich schlecht sind.

Übrigens bin ich nicht sicher, wenn das Konzept eines Doppeltätigkeitsmenüknopfes Richtlinien der Computerzugänglichkeit (a11y) für den GNOME Shell durchbrechen würde, aber angenommen, das Paradigma in Microsoft Windows allgemein ist, ich nicht vermute.

Ich habe eine einfache GNOME Shell-Verlängerung, das demodualmenubutton verursacht, basiert auf dem oben genannten Code, den Sie von meiner GNOME Shell- Verlängerungsweb site herunterladen können.

Genießen Sie!

4 Anmerkungen, zum zu verdoppeln Menüs für einen Knopf GNOME Shell-3.2

  • Ich hasse, so knapp zu sein. Aber warum vergeuden Sie Ihre Zeit auf allen diesen Verlängerungen (diesen benutze ich Tageszeitung übrigens)? Ich sehe Ihren Namen und diese Web site über dem Netz ständig - ich erlerne von den Seiten, die Sie bekannt geben, aber eine Frage bleibt: Warum nicht führen Sie die Kodierung für GNOME?

    • Wirklich wende ich sehr wenig Zeit oder Energie auf GNOME-Verlängerungen auf. Einfach haben Sie nicht die Zeit oder die Neigung. Was die Führung anbetrifft der Kodierung für GNOME, strebt es nicht an zu geschehen, während ich mit dem Entwurf und der Durchführungsphilosophie der GNOME Shell-Kernmannschaft anderer Meinung bin.

  • LONNIEFUTURE

    Ich war über Ihr copyright neugierig. Bedeutet das copyright Ihre Arbeit kann nicht neuverteilt werden? Warum copyright FOSS?

    • Lizenz und copyright ist zwei verschiedene Konzepte, die häufig in der FOSS Welt verwirrt werden. Meine Arbeit kann pro GPL neuverteilt werden zur Verfügung stellte Ihnen Urlaub mein Urheberrechtsvermerk auf ihr. Sie können Ihren eigenen Urheberrechtsvermerk addieren, wenn Sie meine Arbeit ändern, aber Sie meinen Urheberrechtsvermerk an der richtigen Stelle lassen müssen.

      In den USA und in den meisten Ländern, haben Sie automatisch copyright zu jeder möglicher erschienenen Arbeit. Das geschieht durch Rückstellung, sobald die Arbeit veröffentlicht wird. In der Tat müssen Sie Ihre Arbeit in das public domain ausdrücklich legen, wenn Sie die Arbeit urheberrechtlich geschützt nicht sein wünschen.

      Sehen Sie http://www.gnu.org/licenses/gpl-faq.html#RequiredToClaimCopyright für weitere Informationen.

Lassen Sie eine Antwort-