Zwischen 2 X Display switchen.



  • Hi,

    Ich würde gern ein Progrämmchen schreiben, das zwischen zwei X Displays hin und her springt, wenn es aufgerufen wird.

    Pseudocode:
    Get Display
    set Mouse-Focus to other Display
    exit

    Sieht recht einfach aus, aber ich tüftel da schon seit zwei Wochen rum. OK man muss dazu sagen, das ich noch keine Erfahrung in C hab, jedoch sollte das in dem Sinne machbar sein da ich mich mit PHP, Perl, Java einigermassen auskenne.

    Ich hab erstmal langsam angefangen:

    #include <stdio.h>
    #include <X11/Xlib.h>
    
    // Kompilieren mittels: cc -I/usr/X11R6/include cd.c && a.out
    int main() {
    //char sDisplay[] = "Test";
        char *sDisplay = getenv("DISPLAY");
        char *sHost = getenv("HOSTNAME");
        //char *sDefaultDisplay = ":0.0";
        printf("Hallo %s\n",sDisplay);
        printf ("Host: %s\n",sHost);
    }
    

    Fehlermeldungen und ausgaben:

    FreeBSD 5.3 $ cc -I/usr/X11R6/include cd.c && a.out
    cd.c: In function `main':
    cd.c:7: warning: initialization makes pointer from integer without a cast
    cd.c:8: warning: initialization makes pointer from integer without a cast
    Hallo :0.0
    Host: (null)
    

    Mein Probleme bisherigen Problem:
    Warum ist Host: (null)?
    Ich habs auch mal mit variablen versucht: "char sDisplay" aber dann kann ich das Programm nicht kompilieren. Warum?

    Gruss schibumi



  • wirklich seltsam, dass HOSTNAME NULL zurückliefert, vielleicht ist bei dir gar nicht besetzt (nur dann liefert getenv NULL). Mach echo $HOSTNAME und schau, ob die Variable überhaupt besetzt ist. Bei mir läuft dein Code einwandfrei.

    char sDisplay wird wohl nicht gehen, weil getenv ein char* und kein char zurückliefert.



  • Die Warnungen kommen übrigens daher, dass du nicht stdlib.h eingebunden hast. Deswegen nimmt der Compiler implizit int als Rückgabetyp von getenv an.

    char ist ja nur ein einzelnes Zeichen. char* ist ein Zeiger auf ein Zeichen, dem in der Regel mehrere Zeichen folgen, bis ein Zeichen gleich 0 ist.



  • @ supertux: HOSTNAME ist gesetzt - deshalb war ich immer so verwundert 😞

    FreeBSD 5.3 $ echo $HOSTNAME
    develop.openprotocol.jk
    

    Habs jetzt als Workaround hardgecodet.

    @ kingruedi: danke für den Tipp mit der stdlib.h - klappt jetzt ohne Warnung
    Ich hab auch mal folgendes ausprobiert (DISPLAY in Zeichenkette speichern):

    char sDisplay[] = getenv("DISPLAY");
    

    Als Fehlermeldung bekomme ich dann:

    cd.c:7: error: invalid initializer
    

    Sieht für mich so aus, als könnte man Umgebungsvariblen nicht in Zeichenketten speichern - Ist dafür zwingend immer ein Zeiger notwendig?

    Next Step:
    Als Nächstes will ich ein IF zur Unterscheidung des Displays einbauen.

    #include <stdio.h>
    #include <X11/Xlib.h>
    #include <stdlib.h>
    
    int main() {
        char *sDisplay = getenv("DISPLAY");
        //char sHost[] = "develop.openprotocol.jk";
    
        char sDisplayLeft[] = ":0.0";
        char sDisplayRight[] = ":0.1";
    
        printf("Current display %s\n",sDisplay);
    
        if (sDisplay == sDisplayLeft) {
            printf ("Display left: %s\n",sDisplayLeft);
        } else {
            printf ("Display right: %s\n",sDisplayRight);
        }
    }
    

    Output:

    FreeBSD 5.3 $ make && twist
    cc -I/usr/X11R6/include -I/usr/include -I/usr/src/include/ -o twist cd.c
    Current display :0.0
    Display right: :0.1
    

    Irgendwie scheint die Bedingung in IF nicht zu greifen obwohl meiner Meinung nach:

    :0.0 == :0.0
    

    drinstehen sollte und somit das Programm in den IF-Zweig springen sollte und nicht in ELSE.

    Nochwas. Meine main() funktion gibt ja nix zurück. Deshalb sollte es meiner Meiung nach korrekterweise void main() und nicht int main() heissen. Wenn ich das jedoch angeben erhalten ich folgende Warnung:

    cd.c: In function `main':
    cd.c:6: warning: return type of 'main' is not `int'
    

    Funktioniert zwar, jedoch wäre es toll den Grund für die Warnung zu wissen.
    Gruss schibumi



  • Hab das IF Problem gelöst:

    if (strcmp (sDisplay,sDisplayLeft) == 0)
    

    Gruss schibumi



  • schibumi schrieb:

    Sieht für mich so aus, als könnte man Umgebungsvariblen nicht in Zeichenketten speichern

    doch, char* zeigt auch auf eine Zeichenkette ... die Intialisierung char a[] = ??? kann nur funktionieren, wenn ??? ein String der Art "···" ist, abr nicht, wenn du eine char* funktion benutzt. Deshalb kommt der Fehler.

    schibumi schrieb:

    Ist dafür zwingend immer ein Zeiger notwendig?

    ja, getenv kümmert sich darum, die Zeichenkette zu erstellen, du brauchst nur eine Variable, die darauf zeigt.

    schibumi schrieb:

    Nochwas. Meine main() funktion gibt ja nix zurück. Deshalb sollte es meiner Meiung nach korrekterweise void main() und nicht int main() heissen. Wenn ich das jedoch angeben erhalten ich folgende Warnung:

    cd.c: In function `main':
    cd.c:6: warning: return type of 'main' is not `int'
    

    Funktioniert zwar, jedoch wäre es toll den Grund für die Warnung zu wissen.
    Gruss schibumi

    nein, nicht void main()! Das ist Kässe! main ist ist und liefert 0, falls alles gut gelaufen ist, eine Zahl ungleich 0 sonst. Deine Main Funktion sollte 0 zurückliefern, falls es keine Fehler verursachen wurden, da aber bei dir keine Fehler pasieren können, mach einfach am Ende ein return 0;
    Denke immer daran, dass deine Programme durchaus von einem Skript ausgeführt werden können, die die Rückgabe von main brauchen, z.b.

    #!/bin/sh
    
    (twist && echo "Alles Supi gelaufen") || echo "Oh! Es gab Fehler"
    

    und wenn main nichts zurückliefert, dann kann obgies Bsp. nicht funktionieren.



  • nein, nicht void main()! Das ist Kässe! main ist ist und liefert 0, falls alles gut gelaufen ist, eine Zahl ungleich 0 sonst...

    Ok.

    Nun kämpfe ich gerade damit ein Display zu öffen. Ich hab mich dabei mal an
    http://tronche.com/gui/x/xlib/display/opening.html orientiert:

    #include <stdio.h>
    #include <X11/Xlib.h>
    #include <stdlib.h>
    
    // Kompilieren mittels: make d
    int main() {
        char *sDisplay = getenv("DISPLAY");
        //char *sDisplay = "develop.openprotocol.jk:0.0";
        //printf("Current display: %s\n",sDisplay);
        Display *dpy;
        dpy = XOpenDisplay(sDisplay);
        XCloseDisplay(dpy);
    }
    

    Fehlermeldung:

    FreeBSD 5.3 $ make d 
    cc -I/usr/X11R6/include -I/usr/include -I/usr/src/include/ -I/usr/X11R6/lib -o disp display.c
    /var/tmp//ccUsqYEj.o(.text+0x36): In function `main':
    : undefined reference to `XOpenDisplay'
    /var/tmp//ccUsqYEj.o(.text+0x47): In function `main':
    : undefined reference to `XCloseDisplay'
    *** Error code 1
    
    Stop in /home/jerik/toogleDisplay/ctest.
    

    Irgenwie scheinen da Referenzen nicht ganz zu stimmen. Ein grep XOpenDisplay /usr/X11R6/include/X11/Xlib.h liefert mir *extern Display XOpenDisplay( XOpenDisplay ist also in der Header-Datei vorhanden. Nun weiss ich nicht ob ich den aufruf richtig gemacht hab, jedoch hab ich mir mehrere Beispiele angesehen in denen das auf diese Art und Weise gemacht wird. Sollte also stimmen. Was mich jedoch stuzig mach ist *Display dpy Woher kommt Display. Es scheint mir auf anhieb kein regulärer Datentyp zu sein, also müsste es ein benutzerdefinierter Datentyp sein. Aber wo ist der definiert, bzw. wie sieht er aus damit ich selbst definieren kann?

    gruss schibumi



  • schibumi schrieb:

    Fehlermeldung:

    FreeBSD 5.3 $ make d 
    cc -I/usr/X11R6/include -I/usr/include -I/usr/src/include/ -I/usr/X11R6/lib -o disp display.c
    

    Du solltest jedenfalls dem Linker mitteilen, daß der die X11-lib hinzufügen muß (-lX11 o.ä wobei das ein kleines l sein sollte). Das Verzeichnis dafür solltest Du mit -L/usr/X11R6/lib angeben, nicht mit -l ...



  • Hi Jungs,

    *** Habs geschafft - oleole ***
    Dank euch allen für die Hilfe. Ohne die hätte ich es bestimmt nicht so leicht geschafft.

    Das Programm gehört wohl eher in die Kategorie Quick 'n Dirty. Macht aber genau das was ich will:

    #include <X11/Xlib.h>
    #include <unistd.h>
    #include <stdlib.h>
    
    // Quick and Dirty Solution but it fits to me ;)
    int main() {
    
            char *currDisplay = getenv("DISPLAY");
            char sDisplayLeft[] = ":0.0";
            char sDisplayRight[] = ":0.1";
            char *moveToDisplay; 
            Display *d;
            Screen *s;
    
            // Auf Welchem Display bin ich und wo will ich hin
            if (strcmp (currDisplay,sDisplayLeft) == 0) {
                    moveToDisplay = sDisplayRight;
            } else {
                    moveToDisplay = sDisplayLeft;
            }
    
            d = XOpenDisplay(moveToDisplay);
            if ( d ) {
          // Window erstellen
                    Window w = XCreateWindow(d, 
                            DefaultRootWindow(d), 
                            0, 0, 200, 100, 0, 
                            CopyFromParent, CopyFromParent,
                            CopyFromParent, 0, 0);
    
              s = XScreenOfDisplay(d, 0);
          // Window anzeigen
          //XMapWindow(d, w); // Wenn Enkommentiert - wird Window angezeigt
              XWarpPointer (d, None, w, 0, 0, 0, 0, s->width/2, s->height/2); // zwingend notwendig
              XFlush(d);
    
          // Lang genug schlafen um Window anzuzeigen
          //sleep(2); Wenn Window angezeigt - wie lange
        }
      return 0;
    }
    

    Gruss schibumi


Anmelden zum Antworten