Anmelden

Archiv verlassen und diese Seite im Standarddesign anzeigen : [SDL]Neues Fenster (als Thread gestartet) klaut mir die Tastatur im Hauptprogramm



stexie
14-06-2003, 19:35
Ich bräuchte Eure Hilfe für folgendes Problem:

Ich habe ein Hauptprogramm zur Steuerung eines Automaten geschrieben (in C unter SUSE Linux 8.0), das u. a. kontinuierlich die Tastatur abfragen muss. Das Hauptprogramm funktioniert soweit einwandfrei.

Zusätzlich habe ich eine grafische Oberfläche geschrieben (unter C in SDL). Diese Grafik bedient sich einiger globalen Variablen aus dem Hauptprogramm und wird vom Hauptprogramm einfach als Thread (pthread_create()) gestartet. Die Grafik brauch nur auf den Bildschirm ausgegeben zu werden und benötigt keine Rückmeldungen (Buttons, Eingabefelder, o. ä.) vom Anwender. Die gesamte Steuerung des Automaten übernimmt das Hauptprogramm durch die Abfrage der Tastatur.

Jetzt das Problem. Sobald die Grafik (als Thread) gestartet wird, wird SDL initialisiert und erzeugt damit beim Aufruf auch ein neues Fenster. Das neue Fenster zieht damit allerdings auch den Focus auf sich (wahrscheinlich X11), so dass auch die Tastatur (also die Standardeingabe) auf die Grafik übertragen wird. Das Hauptprogramm empfängt jetzt keine Eingaben der Tastatur mehr.

Auf dem Entwicklungsrechner konnte ich jetzt einfach einmal in das Terminal klicken, in dem das Hauptprogramm lief und damit wurde auch die Tastatureingabe wieder auf das Hauptprogramm umgeleitet. Auf dem Automatenrechner habe ich aber dazu nicht die Möglichkeit. Erstens habe ich da keine Maus und zweitens ist die Grafik im Vollbild dargestellt und ich komme nicht mehr an das Hauptprogramm.

Jetzt meine Fragen:

Kann ich direkt unter C den Focus wieder auf das aufrufende Programm zurückgeben oder bei der Erzeugung des Threads die Standardeingabe direkt beim aufrufenden Programm belassen? Mit dem Kopieren und Umleiten der Standardeingabe habe ich schon herumgebastelt, bisher aber ohne Erfolg. Ich möchte die Grafikroutine auch nicht als neuen Prozess starten, weil ich dann die relevanten Daten z. B. über eine pipe schaufeln müsste und dann Probleme mit der Synchronisation bekomme. Vielleicht kann man die Grafik ja auch ohne die Tastatur initialisieren? Oder gibt es eine X11/Linux Lösung bei der zwar ein neues Fenster geöffnet wird, allerdings dieses neue Fenster nicht den Focus erhält?

Also Ihr seht, ich bin für jede Hilfe und alle Ideen dankbar. Ich sitze jetzt schon seit einigen Tagen an diesem Problem, deshalb seit mir nicht böse wenn ich etwas mehr geschrieben habe und dieses Posting vielleicht in einem anderen Board oder einer anderen Liste noch mal auftaucht.

pik7
14-06-2003, 20:41
hallo,

man kann (bei mir jedenfalls) den Windowmanager (Enlightenment)
so einstellen das der Focus im aufrufenden Window verbleibt,
oder eben das neue Window den Focus sofort bekommt,
oder der Focus dem Mauszeiger folgt oder der Focus nur bei Click usw und so fort.
Schau mal ob bei sowas gibt wie Focus Settings.
Ist natürlich nicht die optimale Lösung deines Problems.

Normalerweise empangen X-programme nähmlich
KeyPress,KeyRelease -events usw. vom Xserver der sich nähmlich die
Tastatur unter den Nagel gerissen hat.
Auch "Terminal Programme" like Xterm,Eterm usw. die leiten dann
die eingabe weiter zu den Konsoleprogrammen.

Hoffe konnte mich verständlich ausdrücken.

gruß

DanDanger
14-06-2003, 21:00
Soviel ich weiss, kann mann dem initSDL(....) Befehl von SDL einen Parameter übergeben, der entscheidet ob das neue SDL-Fenster den Eingabefocus erhält.

Ich würde mich da mal an die SDL-Mailingliste wenden (die Deutsche SDL-Mailingliste gibt's unter http://www.libsdl.de ).


Gruss
DanDanger

stexie
14-06-2003, 23:53
Erstmal herzlichen Dank Euch beiden für die schnellen Antworten. Leider initialisiert die SDL das Fenster vollautomatisch und ich habe bis jetzt keinen Weg gefunden, die Fensteroptionen beim Erzeugen des Fensters zu beeinflussen. Die Maillingliste der libsdl hab ich bereits kontaktiert (mehrfach), allerdings scheint auch dort niemand weiter zu wissen. Die Liste ist aber auch recht schwach was die Teilnehmerzahl angeht.

Also, vielen Dank, ich versuch halt weiter mein Glück.

Vielleicht fällt ja noch jemandem was ein, nur zu...

stexie
17-06-2003, 13:45
Ich bin jetzt meinem Problem ein wenig näher gerückt. So wie es aussieht habe ich bei der Erzeugung des neuen Fensters auf SDL-Ebene keine Möglichkeit, den Tastaturfocus beim aufrufenden Programm zu belassen. SDL greift wohl auf die Standard-Libary Xlib (X11) zurück.

Zur Widerholung: Ich starte aus einem laufenden Hauptprogramm einen neuen Thread und in diesem neuem Thread eine Grafik (programmiert mit SDL). Sobald diese Grafik in einem neuen Fenster geöffnet wird übernimmt das neue Fenster den Focus und damit auch die Tastaturkontrolle. Die Tastatur soll aber weiterhin vom (jetzt im Hintergrund laufenden) Hauptprogramm abgefragt werden können.

Jetzt also meine neue Frage: Ist es unter X11 (xlib) möglich, den Focus nicht an das neue Fenster zu übergeben? Oder kann ich den Focus in ein laufendes Programm oder an eine Konsole (in der z. B das Hauptprogramm läuft) zurückgeben. Vielleicht gibt es ja auch unter xlib die Möglichkeit, sich den Focus vom neu erzeugten Fenster zurückzuholen.

Ich habe Funktionen wie z. B. XSetInputFocus() oder XGetInputFocus gefunden, weiß dann allerdings dabei nicht, welche Argumente ich dort einsetzten muss. Wie kann ich z. B. den Pointer der Konsole erfragen, auf den ich den Focus setzten will.

Bin für jede Hilfe dankbar, auch für Verweise auf Homepages oder andere Boards oder Foren.

Vielen Dank

stexie

anda_skoa
17-06-2003, 16:39
Warum so umständlich mit Focus "Verschieben" arbeiten?

Wenn das Fenster den Focus hat, dann bekommt es auch die Key Events, die du dann ja auch verarbeiten kannst, oder?

Ciao,
_

stexie
18-06-2003, 07:24
Hi,

den Tastaturfocus benötige ich im Hauptprogramm. Aus diesem Hauptprogramm wird erst der Thread mit der Grafik erzeugt. Damit bekommt dann die Grafik den Focus. Damit klaut die Grafik mir die Tastatur sozusagen im (jetzt im Hintergrund) laufenden Hauptprogramm. Da aber alle Routinen die die Tastatur abfragen und weiterverarbeiten bereits im Hauptprogramm laufen, muss ich den Focus wieder auf das Hauptprogramm "zurückbiegen".

anda_skoa
18-06-2003, 09:58
Ich hatte den Eindruck, dass in SDL die Events immer mit einer Funktion bearbeitet werden, also unabhängig, welches Fenster den Focus hat.
SDL_WaitEvent oder so.
Da diese Funktion kein Fenster als Parameter hat, nahm ich an, dass es Events der Applikation bearbeitet.

Aber auch wenn jedes Fenster die Keyboard Events extra bekommt, sollte es doch nicht schwer sein, sie an das andere Fenster weiter zu reichen, oder?

Ciao,
_

stexie
18-06-2003, 10:17
naja, genau das ist mein Problem. SDL macht ja nur ein Fenster los während das Hauptprogramm im Hintergrund in der Konsole weiterläuft. Die ein neue SDL-Fenster übernimmt dann den Tastaturfocus. Wie bekomme ich jetzt die Tastaturkontrolle wieder auf das Hauptprogramm, bzw in das Konsolenfenster umgeleitet?

anda_skoa
18-06-2003, 12:38
Ich glaube, wir reden aneinander vorbei.

Welche der SDL Event Funktionen verwendest du?
WaitEvent? PollEvent?

Irgendwie kann ich mir nicht vorstellen, dass SDL für jedes Fenster eine eigene Eventloop hat.

Ciao,
_

stexie
18-06-2003, 12:52
Ich nutze überhaupt keine SDL Event Funktionen. Genau das will ich ja nicht. Die SDL-Grafik ist eine reine grafische Oberfläche, die nur den aktuellen Zustand für den Zustandsautomaten visuell ausgibt. Die Grafik soll und muss keine Rückmeldungen verarbeiten. Keine Buttons, keine Eingaben, keine Mausfunktionen - nichts!

Genau das ist ja das Problem. Das Hauptprogramm verarbeitet die Tastatureingaben und sobald ich die SDL-Grafik (in einem Thread) aus dem Hauptprogramm aufrufe erzeugt die Grafik das Fenster und die X11 (xlib) reißt sich mit der Initialisierung des neuen Fensters auch die Tastatur unter den Nagel...

Auf dem Entwicklunsrechner kann ich jetzt einmal mit der Maus in das Konsolenfenster klicken in dem das Hauptprogramm läuft und damit die Tastaturkontrolle (den Focus) wieder an das Hauptprogramm zurückgeben. Allerdings geht das auf dem Microboard auf dem das System später läuft nicht mehr und somit muss ich diese Focusumschaltung irgendiwe implementieren.

Ich hoffe jetzt hab ich die Sache etwas besser erklärt.

Bis hierher aber erstmal Danke für Deine Bemühungen, vielleicht fällt Dir (oder allen anderen) ja noch was ein.

pulp
18-06-2003, 14:19
also focus bekommst du mit:

XSetInputFocus(display, window, RevertToPointerRoot,
CurrentTime);

was wohl nicht geht da du wahrscheinlich kein display hast.


focus wieder wegbekommen geht mit:

XSetInputFocus(display, PointerRoot, RevertToNone,
CurrentTime);

das vielleicht in dem grafik fenster starten.

was auch noch gibt:

http://polar.gsfc.nasa.gov/software/grads/win32/X11R6.3/X11R6.4/doc/X11/XGrabKeyboard

gruss pulp

pulp
18-06-2003, 14:29
hab noch was gefunden:

http://www.linux-magazin.de/Artikel/ausgabe/2000/03/SDL/sdl.html

in dem beispiel machen die nen neues fenster aber die event werden im hauptprogramm abgefangen

stexie
18-06-2003, 15:09
herzlichen Dank pulp,

für die Befehle XSetInputFocus und XGetInputFocus benötige ich jeweils den Zeiger auf das aktuelle Display (*display). In meinem Fall wäre das der Zeiger auf die aktuelle Konsole, in der das Hauptprogramm läuft. Hast Du vielleicht ne Idee, wie ich an diesen Zeiger komme. Normalerweise wird der Zeiger bei der initialisierung des FGensters als Rückgabewert zurückgegeben, allerdings übernimmt das ja die X11 im Hintergrund.

Gibt es einen Befehl zum Abfragen des aktuellen display-Zeigers?

Das selbe gilt übrigens auch bei XGrabKeyboard :=(

Und die Sache mit dem Artikel aus dem linux Magazin klappt auch nicht. Dort wird die Tastatur und die Maus zwar auch im Hauptprogramm abgefragt, allerdings erst nach der Initialisierung der SDL-Routinen (mit SDL_Init(). Damit hat sich SDL schon die komplette Kontrolle über die Tastatur und die Maus eingestrichen.

In meinem Hauptprogramm muss die Tastatur kontinuierlich abgefragt werden und die SDL wird in einem weiteren Thread erst initialisiert.

Naja, vielleicht hast Du ja Lust und Zeit, mir doch noch weiter zu helfen...

Viele Dank stexie

anda_skoa
18-06-2003, 15:58
Original geschrieben von stexie

In meinem Hauptprogramm muss die Tastatur kontinuierlich abgefragt werden und die SDL wird in einem weiteren Thread erst initialisiert.


Du kannst doch im SDL Thread die Events empfangen, die das SDL Fenster bekommt und and den anderen Thread weiterleiten.

Dann ist egal, welches Fenster den Focus hat.

Ciao,
_

pik7
18-06-2003, 16:44
hallo,



#include <stdio.h>
#include <X11/Xlib.h>

int main()
{

Window win;
Display *disp;
int ret;

disp = XOpenDisplay(NULL);

while(1) {

XGetInputFocus(disp,&win,&ret);
printf("Focus bei Window %x\n" ,win);
sleep(1);

}

return 1;
}


das zeigt dir welches Window momentan den focus besitzt.
(mal was mit dem Mauszeiger rumkurven auf dem Desktop wenn nötig focus durch drücken
ranholen)
Wenn du das einbaust in dein Hauptprogramm
und dam Anfang aufrufst bevor du in den SDL Thread startest
das Window abfrägst was momentan den Focus besitzt also dein Xterm,Eterm oder was auch immer.
Dann mit XSetInputFocus den Focus wieder ranholen.
Window ist ja jetzt bekannt.
Sollte eigentlich funktionieren.
Muss man halt mal ausprobieren.
Find ich natürlich persönlich sch.... diese Methode.
Die Events abfragen ist sauberer.
Aber kannst ja mal ausprobieren.

gruß

pulp
20-06-2003, 19:28
und klappts jetzt ? neugierig bin ;)

stexie
21-06-2003, 13:09
So, erstmal entschuldigt, dass ich mich einige Tage nicht gemeldet habe (ich bin halt neben meiner Diplomarbeit auch noch damit beschäftigt ein Haus zu bauen...).

@ pulp, jaaaaa, die Sache funktioniert jetzt. Ich hab zwar etwas gebraucht um die Sache mit dem XGetInputFocus und XSetInputFocus zu verstehen, aber nach etwas tüftelei (ich bin halt etwas langsamer) funktioniert die Sache jetzt einwandfrei...

deshalb an dieser Stelle ein riesiges Dankeschön an alle die mir hier geholfen haben (war ja doch ne schwere Geburt). Insbesonder gilt mein Dank dem zweitletzten Poster pik7

@pik7 ---> DANKE!!!! Dein Code und Deine Kommentare dazu haben mich auf die richtige Spur gebracht. Ich frage halt jetzt das Fenster ab, das den Focus besitzt bevor ich die SDL-Grafik starte und hole mir den Focus anschließend mit XSetInputFocus zurück.

Natürlich ist diese Methode nicht so sauber, als wenn ich mit den SDL die Events abfrage. Allerdings soll die Grafik vom restlichen Programm absolut unabhängig laufen, damit man die grafische Oberfläche jederzeit austauschen kann (z. B. für ein anderes Displaysystem). Daher blieb mir nicht anderes übrig.

So. Nochmal herzlichen Dank und weiterhin ein schönes Wochenende!!!

stexie

anda_skoa
21-06-2003, 15:11
Original geschrieben von stexie

Natürlich ist diese Methode nicht so sauber, als wenn ich mit den SDL die Events abfrage. Allerdings soll die Grafik vom restlichen Programm absolut unabhängig laufen, damit man die grafische Oberfläche jederzeit austauschen kann (z. B. für ein anderes Displaysystem). Daher blieb mir nicht anderes übrig.


Liesse sich auch lösen.
Die Oberfläche muss dann nur ein Interface der Applikation benutzen, um ihr die Events mitzuteilen.

Gutes Beispiel ist da LICQ, beim dem GUIs Plugins sind.

Ciao,
_