handle keyrepeat specially

This commit is contained in:
David Rose 2003-12-26 23:51:56 +00:00
parent a84c3ffec4
commit 106913d722
2 changed files with 109 additions and 30 deletions

View File

@ -162,11 +162,41 @@ process_events() {
} }
XEvent event; XEvent event;
XKeyEvent keyrelease_event;
bool got_keyrelease_event = false;
while (XCheckIfEvent(_display, &event, check_event, (char *)this)) { while (XCheckIfEvent(_display, &event, check_event, (char *)this)) {
if (XFilterEvent(&event, None)) { if (XFilterEvent(&event, None)) {
continue; continue;
} }
if (got_keyrelease_event) {
// If a keyrelease event is immediately followed by a matching
// keypress event, that's just key repeat and we should treat
// the two events accordingly. It would be nice if X provided a
// way to differentiate between keyrepeat and explicit
// keypresses more generally.
got_keyrelease_event = false;
if (event.type == KeyPress &&
event.xkey.keycode == keyrelease_event.keycode &&
(event.xkey.time - keyrelease_event.time <= 1)) {
// In particular, we only generate down messages for the
// repeated keys, not down-and-up messages.
handle_keystroke(event.xkey);
// We thought about not generating the keypress event, but we
// need that repeat for backspace. Rethink later.
handle_keypress(event.xkey);
continue;
} else {
// This keyrelease event is not immediately followed by a
// matching keypress event, so it's a genuine release.
handle_keyrelease(keyrelease_event);
}
}
WindowProperties properties; WindowProperties properties;
ButtonHandle button; ButtonHandle button;
@ -198,39 +228,16 @@ process_events() {
break; break;
case KeyPress: case KeyPress:
{ handle_keystroke(event.xkey);
_input_devices[0].set_pointer_in_window(event.xkey.x, event.xkey.y); handle_keypress(event.xkey);
// First, get the keystroke as a wide-character sequence.
static const int buffer_size = 256;
wchar_t buffer[buffer_size];
Status status;
int len = XwcLookupString(_ic, &event.xkey, buffer, buffer_size, NULL,
&status);
if (status == XBufferOverflow) {
glxdisplay_cat.error()
<< "Overflowed input buffer.\n";
}
// Now each of the returned wide characters represents a
// keystroke.
for (int i = 0; i < len; i++) {
_input_devices[0].keystroke(buffer[i]);
}
// Now get the raw unshifted button.
ButtonHandle button = get_button(&event.xkey);
if (button != ButtonHandle::none()) {
_input_devices[0].button_down(button);
}
}
break; break;
case KeyRelease: case KeyRelease:
button = get_button(&event.xkey); // The KeyRelease can't be processed immediately, because we
if (button != ButtonHandle::none()) { // have to check first if it's immediately followed by a
_input_devices[0].button_up(button); // matching KeyPress event.
} keyrelease_event = event.xkey;
got_keyrelease_event = true;
break; break;
case EnterNotify: case EnterNotify:
@ -287,6 +294,12 @@ process_events() {
<< "unhandled X event type " << event.type << "\n"; << "unhandled X event type " << event.type << "\n";
} }
} }
if (got_keyrelease_event) {
// This keyrelease event is not immediately followed by a
// matching keypress event, so it's a genuine release.
handle_keyrelease(keyrelease_event);
}
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -597,6 +610,68 @@ setup_colormap(XVisualInfo *visual) {
} }
} }
////////////////////////////////////////////////////////////////////
// Function: glxGraphicsWindow::handle_keystroke
// Access: Private
// Description: Generates a keystroke corresponding to the indicated
// X KeyPress event.
////////////////////////////////////////////////////////////////////
void glxGraphicsWindow::
handle_keystroke(XKeyEvent &event) {
_input_devices[0].set_pointer_in_window(event.x, event.y);
// First, get the keystroke as a wide-character sequence.
static const int buffer_size = 256;
wchar_t buffer[buffer_size];
Status status;
int len = XwcLookupString(_ic, &event, buffer, buffer_size, NULL,
&status);
if (status == XBufferOverflow) {
glxdisplay_cat.error()
<< "Overflowed input buffer.\n";
}
// Now each of the returned wide characters represents a
// keystroke.
for (int i = 0; i < len; i++) {
_input_devices[0].keystroke(buffer[i]);
}
}
////////////////////////////////////////////////////////////////////
// Function: glxGraphicsWindow::handle_keypress
// Access: Private
// Description: Generates a keypress corresponding to the indicated
// X KeyPress event.
////////////////////////////////////////////////////////////////////
void glxGraphicsWindow::
handle_keypress(XKeyEvent &event) {
_input_devices[0].set_pointer_in_window(event.x, event.y);
// Now get the raw unshifted button.
ButtonHandle button = get_button(&event);
if (button != ButtonHandle::none()) {
_input_devices[0].button_down(button);
}
}
////////////////////////////////////////////////////////////////////
// Function: glxGraphicsWindow::handle_keyrelease
// Access: Private
// Description: Generates a keyrelease corresponding to the indicated
// X KeyRelease event.
////////////////////////////////////////////////////////////////////
void glxGraphicsWindow::
handle_keyrelease(XKeyEvent &event) {
_input_devices[0].set_pointer_in_window(event.x, event.y);
// Now get the raw unshifted button.
ButtonHandle button = get_button(&event);
if (button != ButtonHandle::none()) {
_input_devices[0].button_up(button);
}
}
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: glxGraphicsWindow::get_button // Function: glxGraphicsWindow::get_button
// Access: Private // Access: Private

View File

@ -56,6 +56,10 @@ private:
void set_wm_properties(const WindowProperties &properties); void set_wm_properties(const WindowProperties &properties);
void setup_colormap(XVisualInfo *visual); void setup_colormap(XVisualInfo *visual);
void handle_keystroke(XKeyEvent &event);
void handle_keypress(XKeyEvent &event);
void handle_keyrelease(XKeyEvent &event);
ButtonHandle get_button(XKeyEvent *key_event); ButtonHandle get_button(XKeyEvent *key_event);
static Bool check_event(Display *display, XEvent *event, char *arg); static Bool check_event(Display *display, XEvent *event, char *arg);