2014-12-20 4 views
11

Ich möchte in Linux-Desktop-Key-Event-Handling einhaken.Hook in Linux Key Event-Behandlung

Drücken Sie CapsLock sollte eine Art von Befehlszeile eingeben.

Einige der Befehle, die ich implementieren möchten:

  • d/x: Löschen von aktuellen Cursorposition x bis Zeichen. (inspiriert von vi)
  • a: Gehe zum Anfang der Zeile, wie pos1. (inspiriert von Emacs).
  • k: Löschen bis zum Ende der Zeile. (inspiriert von Emacs).
  • ...

Die Befehle sollte in jedem Textfeld arbeiten: Browser, Mail-Client, gnome-Terminal, ...

AFAIK niedriges Niveau xmodmap wird mir hier nicht helfen.

Ist so etwas möglich?

Wo muss ich den Haken platzieren?

Aktuelle Zielplattform ist Ubuntu> = 14,04

Hintergrund: Ich meine Finger zeigen auf F und J behalten möchten, und den Computer zu verwenden, ohne auf die Tastatur. Funktioniert für A-Z seit mehreren Jahren, aber Tasten wie Pos1/End sind nicht einfach zu erreichen.

Bitte hinterlassen Sie einen Kommentar, wenn Sie einen Teil dieser Frage nicht verstehen. Vielen Dank.

aktualisieren

Diese Frage nur darum geht, wie in den Schlüsselereignisbehandlung einzuhaken. Das andere Zeug (Befehlszeile) ist ein anderes Thema. Wie können Sie zum Beispiel CapsLock x fangen?

Update2 Ich sehe, es gibt keine einfache und unkomplizierte Lösung. Wenn Sie keine Antwort haben, aber Sie wissen, wo ich weitere Hilfe finden kann (wie auf der Mailingliste FOO fragen), bitte sagen Sie mir.

Update3 Da einige Leute nicht verstehen, was ich will, ich versuche es zu erklären: Wenn ich Emacs oder bash verwenden Ich fühle mich wie in Kontrolle zu sein, wenn der Computer: es ist wie fliegen, mit nur sehr wenigen Bewegungen Ich kann dem Computer sagen, was ich will. Das Bearbeiten von Text in Webbrowser Textarea, LibreOffice oder mit Thunderbird lässt dieses Gefühl verschwinden. Cursorbewegungen sind umständlich, es fühlt sich nicht nach Fliegen an. Ich möchte den Desktop und nicht nur eine einzelne Anwendung steuern und meine Finger auf die F- und J-Tasten halten.

+3

Lieber unten Wähler: Bitte sagen Sie mir, was mit dieser Frage falsch ist. Was kann ich tun, um es zu verbessern? Zwei Leute unten gewählt weil "zu breit". Ich verstehe es nicht. Was ist zu breit an dieser Frage? – guettli

+0

Sollte das in keinem X-Bildschirm funktionieren? – Basilevs

+0

@Basilevs Nein, für mich ist es genug, wenn X-Desktop läuft. Es muss nicht verfügbar sein, wenn der X-Anmeldebildschirm nach Benutzer/Passwort oder der Textkonsole (Strg-Alt-F1) fragt. – guettli

Antwort

4

Der Brute-Force-Weg wäre zu modyfy/Wiederaufbau xserver-xorg-input-evdev Paket und ersetzen /usr/lib/xorg/modules/input/evdev_drv.so. Ich würde damit beginnen, EvdevQueueKbdEvent() Funktion in xf86-input-evdev-2.9.0/src/evdev.c zu ändern. Sieht nicht sehr elegante Lösung aus, aber ich denke, dass Sie die Tastaturereigniswarteschlange flexibel ändern können.

Eine weniger intrusive Lösung ist unter Verwendung von (einige Details here) und/oder XGrabKeyboard() möglich.

Einige Informationen, die hilfreich sein können here (in Bezug auf XTest-Erweiterung).

+1

Vielen Dank. Dies ist das erste positive Feedback, das ich bekomme. Das Ändern von evdev.c sieht nicht sehr flexibel aus. Meine Erweiterung müsste für jeden xserver kompiliert werden. Vielleicht ist es möglich, die Methode zur Laufzeit zu ersetzen ... – guettli

+0

@guettli, ja, das ist eine Art "Machbarkeitsanalyse". Ich glaube, Sie können den modifizierten/umbenannten 'evdev'-Treiber erstellen und verteilen, wenn keine bessere Lösung gefunden wird, aber es kann mehr Arbeit beim Prototyping erfordern. Und ich bin mir nicht sicher, es ist das größte Problem, das Sie kurzfristig haben werden. – kestasx

3

Eine andere Art, auf Ihre Frage zu schauen: Sie wollen einige spezialisierte window manager. Lesen Sie die Spezifikationen für Details. Lesen Sie vor einer Übersicht von X11.

Oder betrachten Sie einige bestehende X window manager. Es gibt viele von ihnen. Ich vermute, dass ratpoison oder xmonad (oder vielleicht sawfish, etc ...) konfiguriert werden könnte, um Ihre Bedürfnisse zu erfüllen. (Aber ich kenne diese WM nicht gut).

Denken Sie zweimal nach, bevor Sie Ihren Fenstermanager von Grund auf implementieren. Es könnte Jahre der Arbeit bedeuten! AFAIU, ein WM kann Tastatur- oder Mausereignisse umleiten, filtern, erfassen oder synthetisieren.

Natürlich, mit wayland werden die Dinge anders sein.

+0

Ja, die Implementierung eines Fenstermanagers ist eine Menge Arbeit. Ich will das Rad nicht neu erfinden. Meine Lösung sollte für jeden Fenstermanager funktionieren.Ich möchte nur die Tastaturereignisse auf ihrem Weg von der Fingerpresse zur X-Anwendung abfangen und verändern. – guettli

+0

Per Definition kann (oder muss) ein Fenstermanager solche Tastaturereignisse abfangen und sie greifen. Sie benötigen einen Fenstermanager. Wählen Sie einen (oder passen Sie ihn an), um Ihren Bedürfnissen zu entsprechen. Bitte folgen Sie den Links, die ich Ihnen gegeben habe, sie sind relevant! –

+0

Ich weiß, dass ich einen Fenstermanager brauche. Aber eine Lösung, die Sie zwingt, einen speziellen Fenstermanager zu verwenden, ist nicht benutzerfreundlich. Und ich denke, dass es möglich ist, dies mit jedem Fenstermanager zu lösen. – guettli

9

UPDATE

Statt den X-Server zu sagen, das Gerät zu ignorieren, können Sie EVIOCGRAB ioctl verwenden, die ich weiter unten in das Programm aufgenommen.

Sie müssen die folgenden Dinge tun:

1.Der Sie haben CONFIG_UINPUT Modul kompiliert und geladen. Ich glaube, Ubuntu hat es schon. Wenn das Gerät /dev/uinput nicht angezeigt wird, versuchen Sie modprobe -v uinput auszuführen, um das Modul zu laden.

2.Run das folgende Programm als Wurzel und geben ihm den Pfad der Tastaturvorrichtung, wie zB:

./process /dev/input/by-id/usb-Microsoft_Wired_Keyboard_600-event-kbd

Das folgende Programm erstellt eine gefälschte Eingabegerät uinput-sample und leitet alle Ereignisse von einem bestimmten aufgerufen Eingabegerät zu ihm. Ich passte es aus dem Beispiel http://thiemonge.org/getting-started-with-uinput

Sie können es ändern, um Dinge zu tun, die Sie tun möchten.

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <unistd.h> 
#include <fcntl.h> 
#include <errno.h> 
#include <linux/input.h> 
#include <linux/uinput.h> 

#define die(str, args...) do { \ 
     perror(str); \ 
     exit(EXIT_FAILURE); \ 
    } while(0) 

int 
main(int argc, char* argv[]) 
{ 
    int     fdo, fdi; 
    struct uinput_user_dev uidev; 
    struct input_event  ev; 
    int     i; 

    if(argc != 2) die("error: specify input device"); 

    fdo = open("/dev/uinput", O_WRONLY | O_NONBLOCK); 
    if(fdo < 0) die("error: open"); 

    fdi = open(argv[1], O_RDONLY); 
    if(fdi < 0) die("error: open"); 

    if(ioctl(fdi, EVIOCGRAB, 1) < 0) die("error: ioctl"); 

    if(ioctl(fdo, UI_SET_EVBIT, EV_SYN) < 0) die("error: ioctl"); 
    if(ioctl(fdo, UI_SET_EVBIT, EV_KEY) < 0) die("error: ioctl"); 
    if(ioctl(fdo, UI_SET_EVBIT, EV_MSC) < 0) die("error: ioctl"); 

    for(i = 0; i < KEY_MAX; ++i) 
     if(ioctl(fdo, UI_SET_KEYBIT, i) < 0) die("error: ioctl"); 

    memset(&uidev, 0, sizeof(uidev)); 
    snprintf(uidev.name, UINPUT_MAX_NAME_SIZE, "uinput-sample"); 
    uidev.id.bustype = BUS_USB; 
    uidev.id.vendor = 0x1; 
    uidev.id.product = 0x1; 
    uidev.id.version = 1; 

    if(write(fdo, &uidev, sizeof(uidev)) < 0) die("error: write"); 
    if(ioctl(fdo, UI_DEV_CREATE) < 0) die("error: ioctl"); 

    while(1) 
    { 
     if(read(fdi, &ev, sizeof(struct input_event)) < 0) 
      die("error: read"); 

     ev.time.tv_sec = 0; 
     ev.time.tv_usec = 0; 

     if(write(fdo, &ev, sizeof(struct input_event)) < 0) 
      die("error: write"); 
    } 

    if(ioctl(fdo, UI_DEV_DESTROY) < 0) die("error: ioctl"); 

    close(fdi); 
    close(fdo); 

    return 0; 
} 
+0

Vielen Dank für Ihre Antwort. Ich kann C schreiben, aber ich bevorzuge Python. Ich möchte Ihre Lösung in den nächsten Tagen auf http://tjjr.fi/sw/python-uinput/ portieren. – guettli

+0

@guettli, überprüfen Sie meine andere Antwort für Python-Lösung –

+0

Python-uinput kann zum Erstellen von Geräten und zum Auslösen von Ereignissen verwendet werden, nicht zum Erfassen, Klonen und Überwachen vorhandener Geräte. – tuomasjjrasanen

3

Hier ist auch ein Python-Projekt mit uinput Treiber:

http://hetgrotebos.org/wiki/uinput-mapper

+0

Vielen Dank. Sieht genau nach dem aus, was ich gesucht habe – guettli

+0

@guettli, genial. Fühlen Sie sich frei, die Antwort zu akzeptieren ... da jemand anderes das Kopfgeld bekommen hat :) –