Nie jesteś zalogowany.
Jeśli nie posiadasz konta, zarejestruj je już teraz! Pozwoli Ci ono w pełni korzystać z naszego serwisu. Spamerom dziękujemy!

Ogłoszenie

Prosimy o pomoc dla małej Julki — przekaż 1% podatku na Fundacji Dzieciom zdazyć z Pomocą.
Więcej informacji na dug.net.pl/pomagamy/.

#1  2024-12-29 11:34:01

  overcq - Użytkownik

overcq
Użytkownik
Zarejestrowany: 2024-11-17
Serwis

xcb_grab_pointer_unchecked wykonane ponownie z tym samym czasem

Próbuję zaimplementować zaawansowane rozpoznawanie wielokliku w programie korzystającym z XCB. Sprawdzany jest limit czasu od naciśnięcia przycisku do zwolnienia (maksymalny czas naciskania przycisku), od zwolnienia przycisku do zaliczenia kliknięcia (minimalny czas od zakończenia klikania) oraz od ostatniego zwolnienia przycisku do ponownego rozpoznawania klikania (minimalny odstęp pomiędzy klikaniem).

Całość obsługi zdarzeń X Window System jest zawarta w tym pliku źródłowym biblioteki “gui-xcb”. Najpierw przetwarzam w pętli serię przychodzących zdarzeń X, a po tym wykonuję ich interpretację. Natomiast rozpoznawanie wielokliku realizuję przez asynchroniczne (najbardziej neutralne dla przychodzących zdarzeń X) ‘grab’.

W bloku interpretacji – w momencie rozpoczynania klikania wykonuję “xcb_grab_pointer_unchecked”, podając czas odczytany ze zdarzenia X naciśnięcia pierwszego przycisku. Następnie po każdej serii nadchodzących zdarzeń X sprawdzam, czy tryb ‘grab’ jest aktualny, wykonując “xcb_grab_pointer_unchecked” z tym samym czasem. A później sprawdzam, czy upłynął limit czasu, wykonując “xcb_grab_pointer_unchecked” z czasem upływu limitu czasu.
Jeśli wynik “xcb_grab_pointer_unchecked” (otrzymywany przy użyciu “xcb_grab_pointer_reply”) jest “XCB_GRAB_STATUS_SUCCESS”, to rozpoznawanie klikania postępuje dalej. Jeśli wynik pierwszego “xcb_grab_pointer_unchecked” jest inny, to znaczy, że od rozpoczęcia klikania przez użytkownika ustawiony tryb ‘grab’ jest nieaktualny z powodu innych działań w systemie (np. inny program — klient X Window System — włączył tryb ‘grab’ z nowszym czasem). Jeśli wynik drugiego “xcb_grab_pointer_unchecked” jest inny, to znaczy, że jeszcze nie upłynął limit czasu i należy wykonać całość rozpoznawania ponownie po otrzymaniu następnej serii zdarzeń X.
Sprawdzanie ostatniego limitu czasu (minimalnego odstępu pomiędzy klikaniem) dokonuję w obsłudze zdarzenia “XCB_BUTTON_PRESS”, nie dopuszczając wtedy do zaliczenia naciśnięcia przycisku i rozpoczęcia klikania.
Dodatkowo przed oczekiwaniem na upływ limitu czasu, który nie będzie spowodowany przez zdarzenie X (np. naciśnięcie/zwolnienie przycisku), ustawiam, by przy pomocy innego wątku zostało wysłane puste zdarzenie “XCB_CLIENT_MESSAGE” po tym czasie i wtedy “xcb_grab_pointer_unchecked” zostanie przetworzone.

Czas przekazywany do “xcb_grab_pointer_unchecked”/“xcb_ungrab_pointer” jest następujący:
1. W pierwszym wywołaniu “xcb_grab_pointer_unchecked” (sprawdzanie aktualności bieżącego trybu ‘grab’) jest to czas pierwszego naciśnięcia przycisku.
2. Jeśli w drugim wywołaniu “xcb_grab_pointer_unchecked” z czasem upływu limitu wynikiem jest “XCB_GRAB_STATUS_SUCCESS”, to wtedy jest zachowywany ten nowy czas.
3. Gdy po zwolnieniu wszystkich przycisków jest wywoływana “xcb_ungrab_pointer”, to przekazywany jest do niej ostatni z sukcesem użyty czas w “xcb_grab_pointer_unchecked”.
Dzięki takiemu postępowaniu mój tryb ‘grab’ nie koliduje z trybami ‘grab’ innych programów (klientów X).

Jednak opisana powyżej realizacja napotyka następujący problem: pierwsze wywołanie “xcb_grab_pointer_unchecked” kolejnym razem przeważnie wraca z “XCB_GRAB_STATUS_INVALID_TIME”. Jest to raportowane w tej linii.
W systemie Gentoo w menedżerze okien Fluxbox wieloklik pierwszego (zwykle lewego) przycisku jest rozpoznawany poprawnie. Ale w tym menedżerze okien naciśnięcie lewego przycisku wywołuje dodatkowo dwa zdarzenia X: “XCB_LEAVE_NOTIFY” z trybem ‘grab’ oraz “XCB_ENTER_NOTIFY” z trybem ‘ungrab’, więc ich przetwarzanie w programie może zaburzać oryginalne zachowanie, choć nie powinno. A wieloklik innych przycisków bardzo rzadko kiedy jest rozpoznawany poprawnie, a przeważnie jest kasowany ze względu na nieaktualność trybu ‘grab’ w powyżej podanej linii.
W systemie Debian (uruchomionym w maszynie wirtualnej) w domyślnym menedżerze okien wieloklik pierwszego przycisku nie wywołuje tych dodatkowych zdarzeń X, ale nie jest rozpoznawany dla żadnego przycisku.
Pojedyncze kliknięcie dowolnego przycisku jest rozpoznawane zawsze poprawnie.

Fragment loga dla kolejno rozpoznanego wielokliku trzeciego (zwykle prawego) przycisku oraz nierozpoznanego (skasowanego w trakcie) w pierwszym systemie:
20241229T080953.095124|a.out|328081|gui-xcb/x-drv.c|897|E_x_window_D_events|9|button press|x_button->detail|3
20241229T080953.095486|a.out|328081|gui-xcb/x-drv.c|1316|E_x_window_D_events|9|ret->status|0|display->pointer_button_S_grab_time|56320325|display->pointer_button_S_seq_i|1
20241229T080953.095885|a.out|328081|gui-xcb/x-drv.c|1374|E_x_window_D_events|9|ret->status|2|grab_time|56320508
20241229T080953.183771|a.out|328081|gui-xcb/x-drv.c|953|E_x_window_D_events|9|button release|x_button->detail|3
20241229T080953.184361|a.out|328081|gui-xcb/x-drv.c|1316|E_x_window_D_events|9|ret->status|0|display->pointer_button_S_grab_time|56320325|display->pointer_button_S_seq_i|2
20241229T080953.352041|a.out|328081|gui-xcb/x-drv.c|1374|E_x_window_D_events|9|ret->status|2|grab_time|56320596
20241229T080953.352864|a.out|328081|gui-xcb/x-drv.c|897|E_x_window_D_events|9|button press|x_button->detail|3
20241229T080953.353173|a.out|328081|gui-xcb/x-drv.c|1316|E_x_window_D_events|9|ret->status|0|display->pointer_button_S_grab_time|56320325|display->pointer_button_S_seq_i|3
20241229T080953.353525|a.out|328081|gui-xcb/x-drv.c|1374|E_x_window_D_events|9|ret->status|2|grab_time|56320717
20241229T080953.379120|a.out|328081|gui-xcb/x-drv.c|953|E_x_window_D_events|9|button release|x_button->detail|3
20241229T080953.379444|a.out|328081|gui-xcb/x-drv.c|1316|E_x_window_D_events|9|ret->status|0|display->pointer_button_S_grab_time|56320325|display->pointer_button_S_seq_i|4
20241229T080953.379789|a.out|328081|gui-xcb/x-drv.c|1374|E_x_window_D_events|9|ret->status|2|grab_time|56320792
20241229T080953.563896|a.out|328081|gui-xcb/x-drv.c|230|E_x_window_D_events|9|NXP|(x_event->response_type & (0x7f))|33|x_event_window|0
20241229T080953.564331|a.out|328081|gui-xcb/x-drv.c|1316|E_x_window_D_events|9|ret->status|0|display->pointer_button_S_grab_time|56320325|display->pointer_button_S_seq_i|4
20241229T080953.564639|a.out|328081|gui-xcb/x-drv.c|1374|E_x_window_D_events|9|ret->status|0|grab_time|56320792
20241229T080953.564673|a.out|328081|gui-xcb/x-drv.c|1379|E_x_window_D_events|9|click|display->pointer_button|3|display->pointer_button_S_seq_i|4
20241229T080953.564710|a.out|328081|gui-xcb/x-drv.c|1722|E_x_window_D_events|9
20241229T081004.896029|a.out|328081|gui-xcb/x-drv.c|897|E_x_window_D_events|9|button press|x_button->detail|3
20241229T081004.896393|a.out|328081|gui-xcb/x-drv.c|1316|E_x_window_D_events|9|ret->status|0|display->pointer_button_S_grab_time|56332126|display->pointer_button_S_seq_i|1
20241229T081004.896791|a.out|328081|gui-xcb/x-drv.c|1374|E_x_window_D_events|9|ret->status|2|grab_time|56332309
20241229T081004.969875|a.out|328081|gui-xcb/x-drv.c|953|E_x_window_D_events|9|button release|x_button->detail|3
20241229T081004.970192|a.out|328081|gui-xcb/x-drv.c|1316|E_x_window_D_events|9|ret->status|0|display->pointer_button_S_grab_time|56332126|display->pointer_button_S_seq_i|2
20241229T081004.970536|a.out|328081|gui-xcb/x-drv.c|1374|E_x_window_D_events|9|ret->status|2|grab_time|56332383
20241229T081004.971337|a.out|328081|gui-xcb/x-drv.c|1316|E_x_window_D_events|9|ret->status|0|display->pointer_button_S_grab_time|56332126|display->pointer_button_S_seq_i|2
20241229T081004.971623|a.out|328081|gui-xcb/x-drv.c|1374|E_x_window_D_events|9|ret->status|2|grab_time|56332383
20241229T081005.085963|a.out|328081|gui-xcb/x-drv.c|897|E_x_window_D_events|9|button press|x_button->detail|3
20241229T081005.086257|a.out|328081|gui-xcb/x-drv.c|1316|E_x_window_D_events|9|ret->status|2|display->pointer_button_S_grab_time|56332126|display->pointer_button_S_seq_i|3
20241229T081005.086463|a.out|328081|gui-xcb/x-drv.c|1748|E_x_window_D_events|9
20241229T081005.166056|a.out|328081|gui-xcb/x-drv.c|953|E_x_window_D_events|9|button release|x_button->detail|3


Widać, że w obu przypadkach — rozpoznania dwukliku (4, ponieważ naciśnięcie i zwolnienie jest liczone osobno) i jego nierozpoznania — jest w linii 1316 “ret->status” powtórnie równe 0 (czyli “XCB_GRAB_STATUS_SUCCESS” oznaczające aktualność bieżącego trybu ‘grab’), ale w przypadku nierozpoznania wielokliku po drugim naciśnięciu przycisku jest już równe 2 (“XCB_GRAB_STATUS_INVALID_TIME”), co powoduje skasowanie bieżącego rozpoznawania klikania.
Na stronie opisu “xcb_ungrab_pointer” jest napisane, że dla sukcesu operacji czas powinien być nie mniejszy niż “last‐pointer‐grab” oraz nie większy niż bieżący czas ‘servera’ X. Natomiast na stronie opisu “xcb_grab_pointer” nie ma adekwatnej informacji.
W tym programie podaję do “xcb_grab_pointer_unchecked” ponownie ten sam czas, który już był użyty z sukcesem, więc jest nie mniejszy niż “last‐pointer‐grab”.

Zastanawiam się, może menedżer okien włącza w ukryciu tryb ‘grab’ w określonych przypadkach po drugim naciśnięciu przycisku i dlatego czas aktualności bieżącego trybu ‘grab’ jest niepoprawny. Próbowałem też dodawać 1 do kolejno użytego czasu, jeśli byłoby wymaganie, że włączanie trybu ‘grab’ musi być z większą wartością czasu, ale to nie pomogło. Może jest jakiś błąd w programie, ale przecież wypisuję wartości czasu używanego do włączania trybu ‘grab’ i nie zmienia się.
Czy ktoś wie, jaka może być przyczyna błędu “XCB_GRAB_STATUS_INVALID_TIME” w tym programie? Jak to obejść, by zachować pasywny tryb ‘grab’, nie kolidujący z innymi działaniami użytkownika?
Co ewentualnie jeszcze dodatkowo sprawdzić, by szukać przyczyny problemu?


Nie znam się, ale się wypowiem.

Offline

 

Stopka forum

Powered by PunBB
© Copyright 2002–2005 Rickard Andersson
Nas ludzie lubią po prostu, a nie klikając w przyciski ;-)