Nowe posty

xx Dystrybucja pod HP Omen (6)
Wczoraj o 23:30:08
xx [Poradnik] Wyszukiwanie Sterowników (2)
Wczoraj o 21:08:23
lamp Problem z Linux Lite po instalacji (0)
Wczoraj o 19:50:30
xx Ile pingwinów? (1)
Wczoraj o 08:59:24
xx konfiguracja pale moon (0)
2024-03-24, 21:53:42
xx Plasma 6 w Neonie ssie trochę mniej ... (10)
2024-03-23, 02:38:11
xx problem z instalacja sterowników do karty sieciowej (3)
2024-03-18, 18:10:16
xx Plik abc.001 (1)
2024-03-17, 17:48:27
xx Zlecę dopracowanie programu w MatLab (0)
2024-03-13, 15:28:40
xx Linux Mint 21.3 XFCE brak dźwieku po paru minutach (karta muzyczna zintegrowana) (5)
2024-03-12, 23:07:01

Autor Wątek: Powtarzające się wciśnięcie klawisza  (Przeczytany 13499 razy)

msuma

  • Gość
Powtarzające się wciśnięcie klawisza
« dnia: 2010-03-12, 22:18:09 »
Piszę program z użyciem biblioteki GTK. Chciałbym żeby wykonywał pewną funkcję w momencie naciśnięcia klawisza na klawiaturze i inną w momencie zwolnienia go. Niestety GTK nie rozróżnia wciśnięcia klawisza od powtórzenia go, więc trzymając klawisz przez dłuższy czas cykl wciśnięcie-zwolnienie powtarza się wielokrotnie. Czy jest jakiś sposób na ominięcie tego problemu?
Wiem że klawiatura wysyła różne sygnały w zależności od tego czy klawisz był rzeczywiście w tym momencie wciśnięty czy tylko przytrzymany. Można to zaobserwować wykonując polecenie hexdump -x /dev/input/event1 (gdzie /dev/input/event1 to deskryptor klawiatury). Kiedy klawisz jest wciskany jedna z wyświetlanych wartości wynosi 1, kiedy jest zwalniany: 0, a kiedy przytrzymany: 2. Czy używając GTK można jakoś uzyskać dostęp do nieprzetworzonych danych wysyłanych przez klawiaturę w celu rozróżnienia tych przypadków?
Wiem też że można wysłać do układu elektronicznego klawiatury polecenie przełączające ją w tryb, w którym nie wysyła powtórzeń klawiszy (typematic repeat delay i typematic repeat rate), ale nie chciałbym korzystać z tego sposobu.

void klawisz_wcisniety(GtkWidget *widget,  GdkEventKey *event, gpointer  data)
{
/*funkcja wykonywana w momencie wciśnięcia klawisza*/
  uint klawisz;
  uint klawisz_hardware;
 
  klawisz = ((GdkEventKey*)event)->keyval;
  klawisz_hardware = ((GdkEventKey*)event)->hardware_keycode;
 
printf("klawisz wcisnięty: %8hd,%8hd\\n", klawisz, klawisz_hardware);
/*tymczasowa funkcja wyświetlająca kody wciśniętego klawisza*/
}


void klawisz_zwolniony(GtkWidget *widget,  GdkEventKey *event, gpointer  data)
{
/*funkcja wykonywana w momencie zwolnienia klawisza*/
  uint klawisz;
  uint klawisz_hardware;
 
  klawisz = ((GdkEventKey*)event)->keyval;
  klawisz_hardware = ((GdkEventKey*)event)->hardware_keycode;
 
printf("klawisz zwolniony: %8hd,%8hd\\n", klawisz, klawisz_hardware);
/*tymczasowa funkcja wyświetlająca kody zwolnionego klawisza*/
}

int main( int argc, char *argv[])
{
gtk_signal_connect(GTK_OBJECT(window),"key_press_event", G_CALLBACK(klawisz_wcisniety), NULL);
gtk_signal_connect(GTK_OBJECT(window),"key_release_event", G_CALLBACK(klawisz_zwolniony), NULL);
}

john1212

  • Gość
Powtarzające się wciśnięcie klawisza
« Odpowiedź #1 dnia: 2010-03-13, 18:06:08 »
Cytat: msuma
Piszę program z użyciem biblioteki GTK. Chciałbym żeby wykonywał pewną funkcję w momencie naciśnięcia klawisza na klawiaturze i inną w momencie zwolnienia go. Niestety GTK nie rozróżnia wciśnięcia klawisza od powtórzenia go, więc trzymając klawisz przez dłuższy czas cykl wciśnięcie-zwolnienie powtarza się wielokrotnie. Czy jest jakiś sposób na ominięcie tego problemu?
Wiem że klawiatura wysyła różne sygnały w zależności od tego czy klawisz był rzeczywiście w tym momencie wciśnięty czy tylko przytrzymany. Można to zaobserwować wykonując polecenie hexdump -x /dev/input/event1 (gdzie /dev/input/event1 to deskryptor klawiatury). Kiedy klawisz jest wciskany jedna z wyświetlanych wartości wynosi 1, kiedy jest zwalniany: 0, a kiedy przytrzymany: 2. Czy używając GTK można jakoś uzyskać dostęp do nieprzetworzonych danych wysyłanych przez klawiaturę w celu rozróżnienia tych przypadków?
Wiem też że można wysłać do układu elektronicznego klawiatury polecenie przełączające ją w tryb, w którym nie wysyła powtórzeń klawiszy (typematic repeat delay i typematic repeat rate), ale nie chciałbym korzystać z tego sposobu.
Masz rację z tym że na CentOs 5.4 i zapewnie na wszystkich redhat-ach klawiatura to /dev/input/event0

Rozwiązaniem będzie użycie:
GdkEventType type;
 the type of the event (GDK_KEY_PRESS or GDK_KEY_RELEASE)

msuma

  • Gość
Powtarzające się wciśnięcie klawisza
« Odpowiedź #2 dnia: 2010-03-13, 23:15:28 »
Z deskryptorem różnie bywa. Nawet na dwóch komputerach z tym samym systemem deskryptor się różnił. Porzuciłem to podejście bo program musiałem uruchamiać jako root.
Dopisałem zaproponowany przez Ciebie warunek, ale nic się nie zmienia. Problem w tym że klawiatura wysyła powtórzenie klawisza co kilkadziesiąt milisekund (typematic repeat rate), a GDK nie rozróżnia tych powtórzeń od prawdziwych zdarzeń naciśnięcia i zwolnienia klawisza. Pole hardware_keycode w strukturze GdkEventKey powinno zawierać cały kod klawisza generowany przez klawiaturę, ale jest on niestety identyczny dla wciśnięcia, zwolnienia i przytrzymania. Chodzi mi o tę jedną cyferkę rozróżniającą je (0, 1 lub 2). Jak się do niej dostać?
void klawisz_wcisniety(GtkWidget *widget,  GdkEventKey *event, gpointer  data)
{
/*funkcja wykonywana w momencie wciśnięcia klawisza*/
  uint klawisz;
  uint klawisz_hardware;
 
  klawisz = ((GdkEventKey*)event)->keyval;
  klawisz_hardware = ((GdkEventKey*)event)->hardware_keycode;
  GdkEventType typ_zdarzenia;  
  typ_zdarzenia = ((GdkEventKey*)event)->type;
if (typ_zdarzenia == GDK_KEY_PRESS || typ_zdarzenia == GDK_KEY_RELEASE)
{printf("klawisz wcisnięty: %8hd,%8hd\\n", klawisz, klawisz_hardware);}
/*tymczasowa funkcja wyświetlająca kody wciśniętego klawisza*/
}


void klawisz_zwolniony(GtkWidget *widget,  GdkEventKey *event, gpointer  data)
{
/*funkcja wykonywana w momencie zwolnienia klawisza*/
  uint klawisz;
  uint klawisz_hardware;
 
  klawisz = ((GdkEventKey*)event)->keyval;
  klawisz_hardware = ((GdkEventKey*)event)->hardware_keycode;
  GdkEventType typ_zdarzenia;  
  typ_zdarzenia = ((GdkEventKey*)event)->type;
if (typ_zdarzenia == GDK_KEY_PRESS || typ_zdarzenia == GDK_KEY_RELEASE)
{printf("klawisz zwolniony: %8hd,%8hd\\n", klawisz, klawisz_hardware);}
/*tymczasowa funkcja wyświetlająca kody zwolnionego klawisza*/
}

int main( int argc, char *argv[])
{
gtk_signal_connect(GTK_OBJECT(window),"key_press_event", G_CALLBACK(klawisz_wcisniety), NULL);
gtk_signal_connect(GTK_OBJECT(window),"key_release_event", G_CALLBACK(klawisz_zwolniony), NULL);
}
Próbowałem wykluczać powtarzające się pary zdarzeń zwolnienie-naciśnięcie, które mają ten sam czas wystąpienia, ale nie jest to zbyt eleganckie rozwiązanie i nie daje zadowalających rezultatów. Poza ty sprawy bardzo się skomplikują kiedy będę naciskał i puszczał kilka klawiszy jednocześnie.
Znalazłem też w: System/Preferencje/Klawiatura opcję "Powtarzanie naciśnięcia klawisza przy jego przytrzymaniu" (w systemie Ubuntu 9.10). Czy dałoby się zrobić tak żeby była ona wyłączana w momencie uruchomienia programu i włączana z powrotem przy jego zamknięciu?

john1212

  • Gość
Powtarzające się wciśnięcie klawisza
« Odpowiedź #3 dnia: 2010-03-14, 00:42:46 »
Cześć,
Przypuszczam że nie sprecyzowałeś co chcesz.
Cytat: msuma
Piszę program z użyciem biblioteki GTK. Chciałbym żeby wykonywał pewną funkcję w momencie naciśnięcia klawisza na klawiaturze i inną w momencie zwolnienia go. Niestety GTK nie rozróżnia wciśnięcia klawisza od powtórzenia go, więc trzymając klawisz przez dłuższy czas cykl wciśnięcie-zwolnienie powtarza się wielokrotnie. Czy jest jakiś sposób na ominięcie tego problemu?
Wiem że klawiatura wysyła różne sygnały w zależności od tego czy klawisz był rzeczywiście w tym momencie wciśnięty czy tylko przytrzymany. Można to zaobserwować wykonując polecenie hexdump -x /dev/input/event1 (gdzie /dev/input/event1 to deskryptor klawiatury). Kiedy klawisz jest wciskany jedna z wyświetlanych wartości wynosi 1, kiedy jest zwalniany: 0, a kiedy przytrzymany: 2. Czy używając GTK można jakoś uzyskać dostęp do nieprzetworzonych danych wysyłanych przez klawiaturę w celu rozróżnienia tych przypadków?
Wiem też że można wysłać do układu elektronicznego klawiatury polecenie przełączające ją w tryb, w którym nie wysyła powtórzeń klawiszy (typematic repeat delay i typematic repeat rate), ale nie chciałbym korzystać z tego sposobu.
Jest kilka niekonsekwencji. Wiem, że tylko krowa nie zmienia poglądów ale ...

Cytat: msuma
Znalazłem też w: System/Preferencje/Klawiatura opcję "Powtarzanie naciśnięcia klawisza przy jego przytrzymaniu" (w systemie Ubuntu 9.10). Czy dałoby się zrobić tak żeby była ona wyłączana w momencie uruchomienia programu i włączana z powrotem przy jego zamknięciu?

msuma

  • Gość
Powtarzające się wciśnięcie klawisza
« Odpowiedź #4 dnia: 2010-03-14, 01:20:44 »
Nie chciałbym korzystać z tego sposobu, ale jeśli innego nie będzie to dobre i to. Najlepiej byłoby gdyby program miał bezpośredni dostęp do klawiatury, ale do tego musiałby być uruchamiany przez roota. Bardzo dobrze by było gdyby rozróżniał wciśnięcie, zwolnienie i przytrzymanie klawisza. Jeśli nie da się tego osiągnąć to zadowoliłbym się funkcją wyłączającą "Powtarzanie naciśnięcia klawisza przy jego przytrzymaniu" zaraz po uruchomieniu programu i włączającą z powrotem przed jego zamknięciem. Chyba jasno się wyraziłem.
Polecenie zmieniające częstotliwość i opóźnienie to sudo kbdrate -r 10 -d 250 (w tym przypadku 10 znaków na sekundę po 250 milisekundach od wciśnięcia klawisza). Co zrobić żeby program wykonywał je na początku i na końcu i jakie parametry wyłączają powtarzanie klawiszy całkowicie?
Czy ktoś miał kiedyś podobny problem?