Aktuelle Mausposition in der Konsole ermitteln
-
Guten Abend. Ich habe das Problem das ich unter Linux die aktuelle Mausposition in der Konsole auf den Pixel genau ermitteln möchte. Unter Windows habe ich das auch geschafft aber unter Linux habe ich bisher nur die Mausposition für ein ASCII Zeichen ermittelt heißt die einzelnen "Felder" für jeweils ein Zeichen. Kann mir einer weiter helfen?
Danke schon mal im Voraus!
-
Auf der "Konsole" gibt es keine Pixel, wenn Du nicht gerade mit SVGAlib oä. herumhantierst.
Du kannst das aber recht bequem portabel über SDL oä. implementieren.
-
Bei xterms, kde-konsolen und wahrscheinlich den meisten anderen x11-terminal-emulatoren steht in der Umgebungsvariable WINDOWID das xlib-Windowhandle.
Darüber (und evtl. XQueryPointer) ließe sich die Mausposition ermitteln.
-
OK. Danke schon mal. Aber ich bin noch ein totaler Anfänger in Sachen Linuxprogrammierung. Ich zeige euch mal den code den ich momentan habe...
#include <curses.h> #include <stdlib.h> int main() { MEVENT pos; int l_maus; chtype button; initscr(); noecho(); keypad(stdscr,TRUE); l_maus=mousemask(BUTTON1_PRESSED,NULL); while(1) { button=wgetch(stdscr); if(button==KEY_MOUSE) { if(getmouse(&pos)==OK) { wenclose(stdscr,pos.y,pos.x); mvwprintw(stdscr,1,0,"y = %2d x = %2d",pos.y,pos.x); } } wrefresh(stdscr); } endwin(); return 0; }
Der Zeigt mir ja nur jedes Feld an. Könnte mir den vielleicht einer umschreiben?
Gruß Andre
-
//EDIT: Was zur Hölle mach ich denn bei den Code-Tags falsch?oO=
Hi,
Ich würde folgenden Code vorschlagen:#include <stdio.h> #include <X11/Xlib.h> #include <stdlib.h> /*-----------------------------------------------------------------------------------*/ /*main part of the code is taken from: http://rosettacode.org/wiki/Get_mouse_position*/ /*-----------------------------------------------------------------------------------*/ int main() { Display *d; Window inwin; /* root window the pointer is in */ Window inchildwin; /* child win the pointer is in */ int rootx, rooty; /* relative to the "root" window; we are not interested in these, but we can't pass NULL */ int childx, childy; /* the values we are interested in */ Atom atom_type_prop; /* not interested */ int actual_format; /* should be 32 after the call */ unsigned int mask; /* status of the buttons */ unsigned long n_items, bytes_after_ret; Window *props; /* since we are interested just in the first value, which is a Window id */ Window our_window, cur_window; XWindowAttributes rect; /*our window attributes*/ // char *id; /* default DISPLAY */ d = XOpenDisplay(NULL); /*didn't work for me in the gnome-terminal (but works at least in xterminal)*/ // id = getenv( "WINDOWID"); // if( id != NULL) // { // our_window = atoi(id); // } // else/*in case the environment variable is not available we assume the active window to be our terminal*/ // { /* ask for active window (no error check); the client must be freedesktop compliant */ XGetWindowProperty(d, DefaultRootWindow(d), XInternAtom(d, "_NET_ACTIVE_WINDOW", True), 0, 1, False, AnyPropertyType, &atom_type_prop, &actual_format, &n_items, &bytes_after_ret, (unsigned char**)&props); our_window = props[0];/*we assume the active window to be our window or rather terminal*/ // } while(1) { XGetWindowProperty(d, DefaultRootWindow(d), XInternAtom(d, "_NET_ACTIVE_WINDOW", True), 0, 1, False, AnyPropertyType, &atom_type_prop, &actual_format, &n_items, &bytes_after_ret, (unsigned char**)&props); cur_window = props[0]; if( our_window == cur_window)/*check whether our window is still the active one*/ { XGetWindowAttributes(d, our_window, &rect);/*get window attributes - we are interested in its expansion (width and height)*/ XQueryPointer(d, our_window, &inwin, &inchildwin, &rootx, &rooty, &childx, &childy, &mask);/*get mouse position relative to the window*/ if( (childx >= 0 && childx <= rect.width) && (childy >= 0 && childy <= rect.height))/*check whether mouse position is in our window*/ { printf( "Mouse coordinates: %d|%d Button event: %d\n", childx, childy, mask); } } } XFree(props); /* free mem */ XCloseDisplay(d); /* and close the display */ return 0; }
Kurze Erklärung:
Mit Hilfe von XGetWindowProperty besorgen wir uns die Window ID des aktuell aktiven Fensters, von dem wir einfach mal annehmen, dass es auch unser Terminal ist, zumindest beim ersten Aufruf von XGetWindowProperty. (Ich denke das sollte ausreichend sein auch wenn es vielleicht nicht immer korrekt ist.)
Wir merken uns also die Window ID unseres Terminals.
In der while-Schleife ermitteln wir zu Beginn immer die ID des aktuellen Fensters und vergleichen diese mit der Window ID unseres Terminals um sicherzustellen, dass der User zur Zeit im Terminal arbeitet.
Sind beide IDs identisch ermitteln wir die Position der Maus mit Hilfe von XQueryPointer. Wir betrachten die Werte childx und childy welche die Position relativ zum Fenster angeben (rootx und rooty beinhalten die Mausposition global betrachtet). Um sicherzustellen, dass die Maus sich noch im Terminal benötigen wir die Ausdehung des Terminals (der User könnte das Terminal ja vergrößert oder verkleinert haben).
Kurz gesagt ist das Terminal das aktive Fenster und ist die Maus innerhalb des Terminals, geben wir die Mausposition auf dem Terminal aus.
(Generell ist das Programm nicht auf ein Terminal beschränkt weswegen Terminal im Text auch durch Fenster ersetzt werden könnte. Dazu müsste der Code natürlich noch etwas angepasst werden.)Mankos:
- Es gibt sicherlich Fälle in denen das aktive Fenster zum Programmstart nicht das Fenster ist, welches uns interessiert. Es wäre unter Umständen besser das Fenster zu benennen, dann alle Fenster zu durchsuchen ob unser gesetzter Name enthalten ist und schließlich dessen Window ID mit der des aktuellen Fensters zu vergleichen. (aber da ich keine Ahnung habe wie das genau funktioniert habe ich es auch nicht implementiert;))- Die *free-Funktionen am Programmende werden nie erreicht, da man das Programm ja killen musst, um aus der Endlos-Schleife zu kommen.
- Dem Code fehlen mindestens noch einige Abfragen, aber als Grundgerüst ist er denke ich ausreichend. (und besonders schön ist er auch nicht;))
Kompilierung:
gcc -L/usr/lib -lX11 -o main main.c
./main(versteht sich das die Library installiert sein muss;))
(unter Umständen musst du den Pfad (/usr/lib) entsprechen anpassen)Wieso der auskommentierte Teil mit der Umgebungsvariable im Gnome-Terminal nicht funktioniert weiß ich nicht, aber die Window ID aus der Umgebungsvariable und die Window ID die XGetWindowProperty zu Tage fördert passen einfach nicht zusammen und mit der ID aus der Umgebungsvariable funktioniert der Code auch nicht.
Vielleicht kann hier jemand Licht ins Dunkel bringen?!Ich hoffe meine Erklärungen und mein Programm sind halbwegs korrekt. Wenn nicht berichtigt mich. (habe nämlich auch nicht so viel Ahnung davon)
Wie im Quelltext vermerkt stammt der Hauptteil des Codes von:
http://rosettacode.org/wiki/Get_mouse_positionDes weiteren könnte dich folgende Seite interessieren, die "Mausprogrammierung mit ncurses" behandelt:
http://pronix.linuxdelta.de/C/Linuxprogrammierung/Linuxsystemprogrammieren_C_Kurs_Kapitel10b.shtmlmfg
asotbbedit by nman: BBCode aktiviert.
-
asotbb schrieb:
Wieso der auskommentierte Teil mit der Umgebungsvariable im Gnome-Terminal nicht funktioniert weiß ich nicht,
vielleicht exportiert das olle gnome-terminal die variable nicht.
aber die Window ID aus der Umgebungsvariable und die Window ID die XGetWindowProperty zu Tage fördert passen einfach nicht zusammen und mit der ID aus der Umgebungsvariable funktioniert der Code auch nicht.
habe dein beispiel jetzt nicht ausprobiert. Aber ich bekomme bei _NET_ACTIVE_WINDOW die gleiche ID wie in $WINDOWID. Mit wmctrl genauso.
Mit der Variable sollte man also eigentlich nicht das aktive Fenster suchen müssen.
-
Hi,
Ich hab mir das ganze jetzt nochmal etwas genauer angesehen und kam zu folgendem Ergebnis:Um das Problem mal zu verdeutlichen:
=>Führe ich folgende Anweisungen im gnome-terminal aus, erhalte ich:
xwininfo -int -id $WINDOWID
xwininfo: Window id: 62914614 "$USER: ~"
Absolute upper-left X: 1280
Absolute upper-left Y: 49
Relative upper-left X: 0
Relative upper-left Y: 25
Width: 1137
Height: 814xwininfo -int
xwininfo: Please select the window about which you
would like information by clicking the
mouse in that window.xwininfo: Window id: 62914564 "$USER: ~"
Absolute upper-left X: 1280
Absolute upper-left Y: 24
Relative upper-left X: 1280
Relative upper-left Y: 24
Width: 1152
Height: 839=>Selbiges im X-Terminal (xterm):
xwininfo -int -id $WINDOWID
xwininfo: Window id: 88080420 "$USER: ~"
Absolute upper-left X: 1280
Absolute upper-left Y: 24
Relative upper-left X: 1280
Relative upper-left Y: 24
Width: 1150
Height: 837xwininfo -int
xwininfo: Please select the window about which you
would like information by clicking the
mouse in that window.xwininfo: Window id: 88080420 "$USER: ~"
Absolute upper-left X: 1280
Absolute upper-left Y: 24
Relative upper-left X: 1280
Relative upper-left Y: 24
Width: 1150
Height: 837(Ausgabe wurde etwas gekürzt.
Beixwininfo: Please select the window about which you
would like information by clicking the
mouse in that window.klicke ich ins Terminal Fenster)
Wie man sieht, sind die beiden Window IDs die ich von xwinfo erhalte im Gnome-Terminal unterschiedlich wohingegen sie im X-Terminal identisch sind.
(Auch wenn ich den das Verhalten nicht verstehe.)Ich denke, dass irgendwo hier das Problem liegt.
Und das ist der Grund, weshalb ich die Umgebungsvariable im Programm nicht verwende.
Oder mache bzw. sehe ich da irgendetwas falsch?
mfg
asotbbedit by nman: BBCode aktiviert.
-
asotbb schrieb:
Oder mache ich da irgendetwas falsch?
du benutzt das gnome-terminal
-
asotbb schrieb:
//EDIT: Was zur Hölle mach ich denn bei den Code-Tags falsch?oO=
Hint: Es hatte was mit "BBCode in diesem Beitrag deaktivieren" zu tun.
-
Ja genau das habe ich gemeint. Vielen Dank!