atari-home.de - Foren

Software => Coding => Thema gestartet von: Count am Mo 22.02.2021, 19:25:09

Titel: Hilfe! evnt_multi() ignoriert Mausklick
Beitrag von: Count am Mo 22.02.2021, 19:25:09
Hallo zusammen,

ich stehe mal wieder vor einem Rätsel und vielleicht kann mir einer von euch auf die Sprünge helfen, wonach ich suchen muss.

Und zwar habe ich ein GEM-Programm, um verschiedene Daten zu verwalten. Dafür gibt es unterschiedliche Eingabemasken, die in einem Fenster dargestellt werden. Die Masken können über das Pulldown-Menü aufgerufen werden oder auch über Hotkeys. Zu Beginn ist keine Maske geöffnet.

Rufe ich die erste Maske über das Pulldown-Menü auf, ist alles in Ordnung. Verwende ich dafür einen Hotkey, habe ich den Effekt, dass der erste Mausklick nicht erkannt wird. Dabei ist es unerheblich, ob ich vor dem Öffnen der Maske auf dem leeren Desktop rumgeklickt habe oder nicht.

Im Grunde ist es egal, ob ich die Maske über das Pulldown-Menü oder über den Hotkey aufrufe. Der Effekt tritt schlicht dann nicht auf, wenn ich vor dem ersten Öffnen einer Maske irgendwie das Pulldown-Menü aktiviert und die Maustaste gedrückt habe.

Das ganze passiert nur beim ersten Mal. D.h. wenn ich in eine andere Maske wechsle, tritt der Effekt nicht mehr auf.

Hier ist stark vereinfacht die Hauptschleife des Programms. Ich habe mir evnt_ret mal in eine Datei ausgeben lassen und es ist wirklich so, dass MU_BUTTON erst ab dem zweiten Drücken der Maustaste zurückgeliefert wird. Wie gesagt: Es sei denn, ich habe vorher das Pulldown-Menü verwendet und dort bereits einmal die Maustaste gedrückt.

do {
    short evnt_ret;
    short msg[8];
    short mx, my, mk, key, kstat;

    evnt_ret = evnt_multi(MU_MESAG | MU_TIMER | MU_BUTTON | MU_KEYBD,
                          1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, msg, CURSOR_BLINK_RATE,
                          &mx, &my, &mk, &kstat, &key, NULL
                         );

    if ((evnt_ret & MU_TIMER) == MU_TIMER) {
        cursor_blink();
        continue;
    }

    if ((evnt_ret & MU_MESAG) != 0) {
        event_handling(msg);
    }

    if ((evnt_ret & MU_KEYBD) != 0) {
        DO_SOMETHING
    }

    if ((evnt_ret & MU_BUTTON) != 0) {
        DO_SOMETHING
    }
} while (...);

Was kann die Ursache sein?
Titel: Re: Hilfe! evnt_multi() ignoriert Mausklick
Beitrag von: KarlMüller am Mo 22.02.2021, 19:56:52
Was kann die Ursache sein?
Ist ein wenig schwierig zu sagen. Was meinst Du mit "Pulldown-Menü"? Eine mit menu_bar angemeldete Menüzeile?

Welche Lib benutzt Du denn?
Die Zeit für ein MU_TIMER Ereignis wird normalerweise mit zwei Werten angeben. ev_mtlocount, ev_mthicount, wie bei evnt_timer (https://freemint.github.io/tos.hyp/de/evnt.html#evnt_timer). Bei Dir sehe ich nur CURSOR_BLINK_RATE.
Titel: Re: Hilfe! evnt_multi() ignoriert Mausklick
Beitrag von: Chocco am Mo 22.02.2021, 20:06:49
Mir fällt nur auf, dass nach Abfrage des Timer Event mit continue ans Ende der Schleife gesprungen wird. Da in einem Event durchaus mehrere Ereignisse zurückgegeben werden können, wird ein zusätzlich zu MU_TIMER gegebenes Ereignis hier ignoriert.
Titel: Re: Hilfe! evnt_multi() ignoriert Mausklick
Beitrag von: mfro am Mo 22.02.2021, 20:14:26
Was kann die Ursache sein?
Ist ein wenig schwierig zu sagen. Was meinst Du mit "Pulldown-Menü"? Eine mit menu_bar angemeldete Menüzeile?

Welche Lib benutzt Du denn?
Die Zeit für ein MU_TIMER Ereignis wird normalerweise mit zwei Werten angeben. ev_mtlocount, ev_mthicount, wie bei evnt_timer (https://freemint.github.io/tos.hyp/de/evnt.html#evnt_timer). Bei Dir sehe ich nur CURSOR_BLINK_RATE.

die mintlib für gcc will an dieser Stelle einen LONG-Wert anstatt der zwei WORDs sehen. Das passt schon.

Mir fällt nur auf, dass nach Abfrage des Timer Event mit continue ans Ende der Schleife gesprungen wird. Da in einem Event durchaus mehrere Ereignisse zurückgegeben werden können, wird ein zusätzlich zu MU_TIMER gegebenes Ereignis hier ignoriert.
+1
Titel: Re: Hilfe! evnt_multi() ignoriert Mausklick
Beitrag von: Count am Mo 22.02.2021, 20:18:12
Das mit dem Timer-Event passt schon:

(evnt_ret & MU_TIMER) == MU_TIMER

Also nur, wenn ausschließlich das Timer-Event aufgetreten ist.

@KarlMüller: Wie @mfro erwähnt, verwende ich Mintlib.

Kann es vielleicht mit wind_update()-Aufrufen zusammenhängen? Vielleicht mehr Begins als Ends? Das könnte ich noch überprüfen.
Titel: Re: Hilfe! evnt_multi() ignoriert Mausklick
Beitrag von: KarlMüller am Mo 22.02.2021, 20:42:05
@KarlMüller: Wie @mfro erwähnt, verwende ich Mintlib.
Nö die gemlib. Dann bitte in Zukunft dazu schreiben, dass niemand mühsam die Parameter abzählt, weil bei einer Lib was nicht zum offiziellen Aufruft passt.
Titel: Re: Hilfe! evnt_multi() ignoriert Mausklick
Beitrag von: Chocco am Mo 22.02.2021, 20:43:46
Das mit dem Timer-Event passt schon:

(evnt_ret & MU_TIMER) == MU_TIMER

Also nur, wenn ausschließlich das Timer-Event aufgetreten ist.


Mit (event_ret & MU_TIMER) werden doch alle anderen Events ausgeblendet. Mit (event_ret == MU_TIMER) würden nur die ausschließlichen Timer Events abgegriffen.
 
Titel: Re: Hilfe! evnt_multi() ignoriert Mausklick
Beitrag von: Chocco am Mo 22.02.2021, 21:08:46
Kann es vielleicht mit wind_update()-Aufrufen zusammenhängen? Vielleicht mehr Begins als Ends? Das könnte ich noch überprüfen.

Ich hatte es mir häufig einfach gemacht:

do
wind_update( END_UPDATE );
event_multi();
wind_update( BEG_UPDATE );

<Events bearbeiten>

while( !exit_program );
Titel: Re: Hilfe! evnt_multi() ignoriert Mausklick
Beitrag von: Count am Di 23.02.2021, 08:05:47
Mit (event_ret & MU_TIMER) werden doch alle anderen Events ausgeblendet. Mit (event_ret == MU_TIMER) würden nur die ausschließlichen Timer Events abgegriffen.
Nach einer Nacht darüber schlafen, hast du natürlich recht. ;)
Aber das ist leider nicht die Ursache. evnt_multi() liefert wirklich erst beim zweiten Klicken das richtige Event MU_BUTTON zurück.
Titel: Re: Hilfe! evnt_multi() ignoriert Mausklick
Beitrag von: mfro am Di 23.02.2021, 08:08:06
Mit (event_ret & MU_TIMER) werden doch alle anderen Events ausgeblendet. Mit (event_ret == MU_TIMER) würden nur die ausschließlichen Timer Events abgegriffen.
Nach einer Nacht darüber schlafen, hast du natürlich recht. ;)
Aber das ist leider nicht die Ursache. evnt_multi() liefert wirklich erst beim zweiten Klicken das richtige Event MU_BUTTON zurück.

was hast Du konkret geändert?
Titel: Re: Hilfe! evnt_multi() ignoriert Mausklick
Beitrag von: Count am Di 23.02.2021, 08:13:28
Mit (event_ret & MU_TIMER) werden doch alle anderen Events ausgeblendet. Mit (event_ret == MU_TIMER) würden nur die ausschließlichen Timer Events abgegriffen.
Nach einer Nacht darüber schlafen, hast du natürlich recht. ;)
Aber das ist leider nicht die Ursache. evnt_multi() liefert wirklich erst beim zweiten Klicken das richtige Event MU_BUTTON zurück.

was hast Du konkret geändert?
Nichts. Ich schreibe das Ergebnis von evnt_multi() direkt in eine Datei und beobachte das. Und es wird alle 300 ms (CURSOR_BLINK_RATE) MU_TIMER (0x20) zurückgeliefert. Erst nach dem zweiten Mausklick MU_BUTTON (0x02).
Titel: Re: Hilfe! evnt_multi() ignoriert Mausklick
Beitrag von: mfro am Di 23.02.2021, 08:20:24
Hast Du das "continue" rausgemacht?
Titel: Re: Hilfe! evnt_multi() ignoriert Mausklick
Beitrag von: Count am Di 23.02.2021, 08:44:56
Hast Du das "continue" rausgemacht?
Nein, ich habe die Bedingung in (evnt_ret == MU_TIMER) geändert.
Titel: Re: Hilfe! evnt_multi() ignoriert Mausklick
Beitrag von: Count am Di 23.02.2021, 09:06:31
Ich habe jetzt mal in einer Header-Datei, die von jeder Quelldatei eingebunden wird, das wind_update()-Makro umgebogen. Meine eigenen Header-Dateien werden immer erst nach den System-Headerdateien eingebunden, also auch immer nach <gem.h>.
#undef wind_update
#define wind_update(a) my_wind_update(a)
void my_wind_update(short);

Die Funktion sieht so aus:
void my_wind_update(short a)
{
    static const char* what[] = { "END_UPDATE","BEG_UPDATE","END_MCTRL","BEG_MCTRL" };
    FILE*f=fopen("A.TXT","a");
    fprintf(f,"wind_update(%s)\n",what[a]);
    fclose(f);
#undef wind_update
#define wind_update(a) mt_wind_update(a,aes_global)
    wind_update(a);
}

Die Ausgabe in A.TXT zeigt keine Auffälligkeiten:
wind_update(BEG_MCTRL)
wind_update(END_MCTRL)
wind_update(BEG_UPDATE)
wind_update(BEG_MCTRL)
wind_update(END_MCTRL)
wind_update(END_UPDATE)
wind_update(BEG_UPDATE)
wind_update(BEG_MCTRL)
wind_update(END_MCTRL)
wind_update(END_UPDATE)
wind_update(BEG_UPDATE)
wind_update(BEG_MCTRL)
wind_update(END_MCTRL)
wind_update(END_UPDATE)
wind_update(BEG_UPDATE)
wind_update(BEG_MCTRL)
wind_update(END_MCTRL)
wind_update(END_UPDATE)
wind_update(BEG_UPDATE)
wind_update(BEG_MCTRL)
wind_update(END_MCTRL)
wind_update(END_UPDATE)
wind_update(BEG_UPDATE)
wind_update(BEG_MCTRL)
wind_update(END_MCTRL)
wind_update(END_UPDATE)
wind_update(BEG_UPDATE)
wind_update(BEG_MCTRL)
wind_update(END_MCTRL)
wind_update(END_UPDATE)
wind_update(BEG_UPDATE)
wind_update(BEG_MCTRL)
wind_update(END_MCTRL)
wind_update(END_UPDATE)
Titel: Re: Hilfe! evnt_multi() ignoriert Mausklick
Beitrag von: mfro am Di 23.02.2021, 09:15:05
Hast Du das "continue" rausgemacht?
Nein, ich habe die Bedingung in (evnt_ret == MU_TIMER) geändert.

Das ist dann zwar nicht die Ursache für dein Problem, aber trotzdem falsch. Das "continue" hat da nichts verloren, das "==" auch nicht.

Die AES führen bei evnt_multi() unterschiedliche Events, die "quasi-zeitgleich" auftreten, zusammen. Deine Event-Behandlung sollte also immer den Event (mit einer Abfrage auf das gesetzte Bit, also
if (evnt & MU_....)
"rausfischen", den es bearbeiten möchte, aber weiterhin die Behandlung anderer Events *nicht* "abklemmen". Das "continue" macht aber genau das. Zusätzlich bearbeitest Du jetzt einen Timer-Event nur dann, wenn er alleine auftritt.

Mehr kann man erst sagen, wenn Du deinen angepassten Code noch mal zeigst.

Titel: Re: Hilfe! evnt_multi() ignoriert Mausklick
Beitrag von: mfro am Di 23.02.2021, 09:44:50
Darüber hinaus: zu viel (unnötiges) wind_update() bremst das Multitasking.

wind_update(BEG_UPDATE)
...
wind_update(END_UPDATE)

klammert Zeichenoperationen, wo Du (per VDI-Calls) selbst zeichnest (also die Rechteckliste abarbeitest). Der call sorgt (nur) dafür, dass die AES so lange die Rechteckliste "in Ruhe lassen".

wind_update(BEG_MCTRL)
...
wind_update(END_MCTRL)

klammert *nur* "lokale" Mausaktionen (also z.B. wenn Du einen Rahmen aufziehst oder eine Fenster-Formularaktion machst). Das verhindert, dass jemand anders als Du von den Aktionen was mitbekommt.

Titel: Re: Hilfe! evnt_multi() ignoriert Mausklick
Beitrag von: Count am Di 23.02.2021, 11:24:07
Danke, das war der entscheidende Tipp. Ich habe die ganzen wind_update()-Aufrufe nochmal kontrolliert und einiges rausgeschmissen. Jetzt funktioniert alles, wie es soll. Wo genau das Problem lag, kann ich leider nicht sagen.
Titel: Re: Hilfe! evnt_multi() ignoriert Mausklick
Beitrag von: Thorsten Otto am Di 23.02.2021, 12:42:10
Das ist dann zwar nicht die Ursache für dein Problem, aber trotzdem falsch. Das "continue" hat da nichts verloren, das "==" auch nicht.

Das kann man so nicht sagen. Wenn der timer nur für Cursor-Blinken benutzt wird, dann möchte man im allgemeinen nicht daß der blinkt, wenn danach noch andere Aktionen wie redraw ausgeführt werden. Auch möchte man vlt nicht daß er blinkt, solange eine Maustaste gedrückt ist. Jedenfalls habe ich  in einigen meiner Programme was ähnliches drin. Auf jeden Fall dürfte, nach der Änderung auf ==, das keinen EInfluss mehr auf die Button-Events haben. Lässt sich einfach testen, indem man mal MU_TIMER aus der Maske der zu erwartenden Events entfernt.
Titel: Re: Hilfe! evnt_multi() ignoriert Mausklick
Beitrag von: mfro am Di 23.02.2021, 12:51:52
Über das == kann man streiten, auch wenn mir schwerfällt, mir eine Situation vorzustellen, wo ich einen Event nur dann bearbeite, wenn die AES gerade keinen anderen Event (mehr oder weniger zufällig) "dazugepackt" haben.
Wenn es so eine Situation gäbe (mir - soweit ich mich erinnere - noch nicht untergekommen), würde ich das jedenfalls expliziter hinschreiben.

Das continue ist m.E. jedenfalls verkehrt. Da wird potentiell ein (oder mehrere) Event(s) weggeschmissen, der/die so auch nicht wieder auftauch[t|en].
Wenn's beispielsweise das Loslassen einer Maustaste war (auf das man gerade sehnlichst wartet), kann das ziemlich blöd sein und nach dem Fehler kann man sich totsuchen.
Titel: Re: Hilfe! evnt_multi() ignoriert Mausklick
Beitrag von: Thorsten Otto am Di 23.02.2021, 14:44:47
Das continue ist m.E. jedenfalls verkehrt. Da wird potentiell ein (oder mehrere) Event(s) weggeschmissen

Nein. Wenn da steht
if (event_ret == MU_TIMER)
{
    do_something();
    continue;
}

dann ist das lediglich eine kleine Optimierung. In dem Fall waren ja keine anderen bits gesetzt und müssen auch nicht weiter getested werden.
Natürlich müsste man dann theoretisch nochmal extra testen, ob MU_TIMER zusammen mit anderen Events aufgetreten ist. Ob man das will hängt aber von der Anwendung ab. In vielen Fällen wird man MU_TIMER nur behandeln wollen, wenn sonst nichts zu tun war,

PS.: das Problem scheint ja auch gelöst zu sein, und mit MU_TIMER nichts zu tun zu habne.
Titel: Re: Hilfe! evnt_multi() ignoriert Mausklick
Beitrag von: mfro am Di 23.02.2021, 15:46:48
Das continue ist m.E. jedenfalls verkehrt. Da wird potentiell ein (oder mehrere) Event(s) weggeschmissen

Nein. Wenn da steht...

Da hast Du wohl recht. Aber tatsächlich stand da ja was anderes...

Titel: Re: Hilfe! evnt_multi() ignoriert Mausklick
Beitrag von: Count am Di 23.02.2021, 16:09:32
Wenn der timer nur für Cursor-Blinken benutzt wird, dann möchte man im allgemeinen nicht daß der blinkt, wenn danach noch andere Aktionen wie redraw ausgeführt werden. Auch möchte man vlt nicht daß er blinkt, solange eine Maustaste gedrückt ist.

So ist es. Wenn eine Aktion ansteht, wird der Cursor ausgeschaltet, bis wieder eine Texteingabe möglich ist.

Aber davon ab, dass jetzt alles so funktioniert, wie es soll, habe ich vorher noch ein paar Tests mit anderen TOS-Versionen und Emulatoren gemacht. Dabei ist herausgekommen, dass das Problem nur mit TOS 2.06 aufgetreten ist bzw. in Hatari auch hier nicht:

TOS 2.06 auf echter Hardware (MegaSTE): Fehler
TOS 2.06 in Steem 3.2 und 4.0: Fehler
TOS 2.06 in Hatari 2.3.1: OK (!)
TOS 4.04 in Aranym 1.0.2: OK
TOS 3.06 in Hatari 2.3.1: OK
TOS 1.62 in Steem 3.2: OK
TOS 1.04 in Steem 3.2: OK
EmuTOS 1.01 in Steem 3.2: OK
Titel: Re: Hilfe! evnt_multi() ignoriert Mausklick
Beitrag von: Thorsten Otto am Di 23.02.2021, 16:57:41
Emulatoren können einen Einfluss haben, wenn sie schneller als "normal" laufen. Meistens hilft es dann die Doppel-Klick-Geschwindigkeit anzupassen, ansonsten kann es passieren, daß nicht lange genug auf den (möglichen) zweiten Klick gewartet wird.