walk and key event system rework with some regressions

This commit is contained in:
Eduardo Bart
2012-01-15 19:19:52 -02:00
parent 9ec40f016d
commit 44a20222bb
52 changed files with 542 additions and 346 deletions

View File

@@ -27,6 +27,7 @@
WIN32Window window;
#else
#include "x11window.h"
#include <framework/core/clock.h>
X11Window window;
#endif
@@ -39,3 +40,83 @@ void PlatformWindow::updateUnmaximizedCoords()
m_unmaximizedSize = m_size;
}
}
void PlatformWindow::processKeyDown(Fw::Key keyCode)
{
if(keyCode == Fw::KeyUnknown || m_keysState[keyCode])
return;
m_keysState[keyCode] = true;
m_lastKeysPress[keyCode] = -1;
if(keyCode == Fw::KeyCtrl)
m_inputEvent.keyboardModifiers |= Fw::KeyboardCtrlModifier;
else if(keyCode == Fw::KeyAlt)
m_inputEvent.keyboardModifiers |= Fw::KeyboardAltModifier;
else if(keyCode == Fw::KeyShift)
m_inputEvent.keyboardModifiers |= Fw::KeyboardShiftModifier;
m_inputEvent.reset();
m_inputEvent.type = Fw::KeyDownInputEvent;
m_inputEvent.keyCode = keyCode;
if(m_onInputEvent) {
m_onInputEvent(m_inputEvent);
m_inputEvent.reset(Fw::KeyPressInputEvent);
m_inputEvent.keyCode = keyCode;
m_lastKeysPress[keyCode] = g_clock.ticks();
m_firstKeysPress[keyCode] = g_clock.ticks();
m_onInputEvent(m_inputEvent);
}
}
void PlatformWindow::processKeyRelease(Fw::Key keyCode)
{
if(keyCode == Fw::KeyUnknown || !m_keysState[keyCode])
return;
m_keysState[keyCode] = false;
if(keyCode == Fw::KeyCtrl)
m_inputEvent.keyboardModifiers &= ~Fw::KeyboardCtrlModifier;
else if(keyCode == Fw::KeyAlt)
m_inputEvent.keyboardModifiers &= ~Fw::KeyboardAltModifier;
else if(keyCode == Fw::KeyShift)
m_inputEvent.keyboardModifiers &= ~Fw::KeyboardShiftModifier;
if(m_onInputEvent) {
m_inputEvent.reset(Fw::KeyReleaseInputEvent);
m_onInputEvent(m_inputEvent);
}
}
void PlatformWindow::fireKeysPress()
{
// avoid massive checks
if(m_keyPressTimer.ticksElapsed() < 10)
return;
m_keyPressTimer.restart();
for(auto it : m_keysState) {
Fw::Key keyCode = it.first;
bool pressed = it.second;
if(!pressed)
continue;
ticks_t lastPressTicks = m_lastKeysPress[keyCode];
ticks_t firstKeyPress = m_firstKeysPress[keyCode];
if(g_clock.ticksElapsed(lastPressTicks) >= KEY_PRESS_REPEAT_INTERVAL) {
if(m_onInputEvent) {
m_inputEvent.reset();
m_inputEvent.type = Fw::KeyPressInputEvent;
m_inputEvent.keyCode = keyCode;
m_inputEvent.wouldFilter = g_clock.ticksElapsed(firstKeyPress) < KEY_PRESS_REPEAT_DELAY;
m_onInputEvent(m_inputEvent);
}
m_lastKeysPress[keyCode] = g_clock.ticks();
}
}
}

View File

@@ -25,9 +25,15 @@
#include <framework/global.h>
#include <framework/core/inputevent.h>
#include <framework/core/timer.h>
class PlatformWindow
{
enum {
KEY_PRESS_REPEAT_INTERVAL = 30,
KEY_PRESS_REPEAT_DELAY = 500
};
typedef std::function<void(const Size&)> OnResizeCallback;
typedef std::function<void(const InputEvent&)> OnInputEventCallback;
@@ -72,6 +78,7 @@ public:
int getY() { return m_pos.y; }
Point getMousePos() { return m_inputEvent.mousePos; }
int getKeyboardModifiers() { return m_inputEvent.keyboardModifiers; }
bool isKeyPressed(Fw::Key keyCode) { return m_keysState[keyCode]; }
bool isVisible() { return m_visible; }
bool isFullscreen() { return m_fullscreen; }
@@ -85,6 +92,16 @@ public:
protected:
void updateUnmaximizedCoords();
void processKeyDown(Fw::Key keyCode);
void processKeyRelease(Fw::Key keyCode);
void fireKeysPress();
std::map<int, Fw::Key> m_keyMap;
std::map<Fw::Key, Boolean<false>> m_keysState;
std::map<Fw::Key, ticks_t> m_firstKeysPress;
std::map<Fw::Key, ticks_t> m_lastKeysPress;
Timer m_keyPressTimer;
Size m_size;
Point m_pos;
Size m_unmaximizedSize;

View File

@@ -35,7 +35,6 @@ WIN32Window::WIN32Window()
m_maximized = false;
m_minimumSize = Size(16,16);
m_size = m_minimumSize;
m_inputEvent.keyboardModifiers = 0;
m_keyMap[VK_ESCAPE] = Fw::KeyEscape;
m_keyMap[VK_TAB] = Fw::KeyTab;

View File

@@ -82,7 +82,6 @@ private:
HGLRC m_glContext;
bool m_maximized;
Size m_minimumSize;
std::map<int, Fw::Key> m_keyMap;
};
#endif

View File

@@ -39,7 +39,6 @@ X11Window::X11Window()
m_screen = 0;
m_wmDelete = 0;
m_size = Size(16,16);
m_inputEvent.keyboardModifiers = 0;
#ifndef OPENGL_ES2
m_glxContext = 0;
@@ -526,33 +525,41 @@ void X11Window::poll()
while(XPending(m_display) > 0) {
XNextEvent(m_display, &event);
// check for repeated key releases
bool repatedKeyRelease = false;
if(event.type == KeyRelease && XPending(m_display)) {
XPeekEvent(m_display, &peekEvent);
if((peekEvent.type == KeyPress) && (peekEvent.xkey.keycode == event.xkey.keycode) && ((peekEvent.xkey.time-event.xkey.time) < 2))
repatedKeyRelease = true;
}
// process keydown and keyrelease events first
if(event.type == KeyPress || (event.type == KeyRelease && !repatedKeyRelease)) {
// remove caps lock and shift maks
XKeyEvent xkey = event.xkey;
xkey.state &= ~(ShiftMask | LockMask);
// lookup keysym and translate it
KeySym keysym;
char buf[32];
int len = XLookupString(&xkey, buf, sizeof(buf), &keysym, 0);
Fw::Key keyCode = Fw::KeyUnknown;
if(m_keyMap.find(keysym) != m_keyMap.end())
keyCode = m_keyMap[keysym];
if(event.type == KeyPress)
processKeyDown(keyCode);
else if(event.type == KeyRelease)
processKeyRelease(keyCode);
}
// call filter because xim will discard KeyPress events when keys still composing
if(XFilterEvent(&event, m_window))
continue;
// discard events of repeated key releases
if(event.type == KeyRelease && XPending(m_display)) {
XPeekEvent(m_display, &peekEvent);
if((peekEvent.type == KeyPress) &&
(peekEvent.xkey.keycode == event.xkey.keycode) &&
((peekEvent.xkey.time-event.xkey.time) < 2))
continue;
}
// reset inputEvent values, except keyboardModifiers and mousePos
m_inputEvent.type = Fw::NoInputEvent;
m_inputEvent.mouseButton = Fw::MouseNoButton;
m_inputEvent.keyCode = Fw::KeyUnknown;
m_inputEvent.keyText = "";
m_inputEvent.mouseMoved = Point();
m_inputEvent.wheelDirection = Fw::MouseNoWheel;
m_inputEvent.keyboardModifiers = 0;
if(event.xkey.state & ControlMask)
m_inputEvent.keyboardModifiers |= Fw::KeyboardCtrlModifier;
if(event.xkey.state & ShiftMask)
m_inputEvent.keyboardModifiers |= Fw::KeyboardShiftModifier;
if(event.xkey.state & Mod1Mask)
m_inputEvent.keyboardModifiers |= Fw::KeyboardAltModifier;
// discard repated key releases
if(repatedKeyRelease)
continue;
switch(event.type) {
case ClientMessage: {
@@ -614,55 +621,44 @@ void X11Window::poll()
XFlush(m_display);
break;
}
case KeyPress:
case KeyRelease: {
// process text events
case KeyPress: {
// text cant be insert while holding ctrl or alt
if(event.xkey.state & ControlMask || event.xkey.state & Mod1Mask)
break;
// process key text events
KeySym keysym;
char buf[32];
memset(buf, 0, 32);
int len;
// lookup for keyText
if(event.type == KeyPress && !(event.xkey.state & ControlMask) && !(event.xkey.state & Mod1Mask)) {
if(m_xic) { // with xim we can get latin1 input correctly
Status status;
len = XmbLookupString(m_xic, &event.xkey, buf, sizeof(buf), &keysym, &status);
} else { // otherwise use XLookupString, but often it doesn't work right with dead keys
static XComposeStatus compose = {NULL, 0};
len = XLookupString(&event.xkey, buf, sizeof(buf), &keysym, &compose);
}
if(len > 0 &&
// these keys produces characters that we don't want to capture
keysym != XK_BackSpace &&
keysym != XK_Return &&
keysym != XK_Delete &&
keysym != XK_Escape &&
(uchar)(buf[0]) >= 32
) {
//logDebug("char: ", buf[0], " code: ", (uint)buf[0]);
m_inputEvent.keyText = buf;
}
if(m_xic) { // with xim we can get latin1 input correctly
Status status;
len = XmbLookupString(m_xic, &event.xkey, buf, sizeof(buf), &keysym, &status);
} else { // otherwise use XLookupString, but often it doesn't work right with dead keys
static XComposeStatus compose = {NULL, 0};
len = XLookupString(&event.xkey, buf, sizeof(buf), &keysym, &compose);
}
XKeyEvent xkey = event.xkey;
xkey.state = xkey.state & ~(ShiftMask);
len = XLookupString(&xkey, buf, sizeof(buf), &keysym, 0);
if(len > 0 && m_inputEvent.keyText.length() == 0 && keysym != XK_BackSpace &&
keysym != XK_Return &&
keysym != XK_Delete &&
keysym != XK_Escape)
m_inputEvent.keyText = buf;
// filter unwanted characters
if(len == 0 || (uchar)(buf[0]) < 32 || keysym == XK_BackSpace || keysym == XK_Return || keysym == XK_Delete || keysym == XK_Escape)
break;
std::string text = buf;
if(m_keyMap.find(keysym) != m_keyMap.end())
m_inputEvent.keyCode = m_keyMap[keysym];
//logDebug("char: ", buf[0], " code: ", (int)((uchar)buf[0]));
m_inputEvent.type = (event.type == KeyPress) ? Fw::KeyPressInputEvent : Fw::KeyReleaseInputEvent;
if(m_inputEvent.keyCode != Fw::KeyUnknown || !m_inputEvent.keyText.empty())
if(m_onInputEvent && text.length() > 0) {
m_inputEvent.reset(Fw::KeyTextInputEvent);
m_inputEvent.keyText = text;
m_onInputEvent(m_inputEvent);
}
break;
}
case ButtonPress:
case ButtonRelease: {
m_inputEvent.reset();
m_inputEvent.type = (event.type == ButtonPress) ? Fw::MousePressInputEvent : Fw::MouseReleaseInputEvent;
switch(event.xbutton.button) {
case Button1:
@@ -694,6 +690,7 @@ void X11Window::poll()
}
case MotionNotify: {
m_inputEvent.reset();
m_inputEvent.type = Fw::MouseMoveInputEvent;
Point newMousePos(event.xbutton.x, event.xbutton.y);
m_inputEvent.mouseMoved = newMousePos - m_inputEvent.mousePos;
@@ -722,6 +719,8 @@ void X11Window::poll()
if(needsResizeUpdate && m_onResize)
m_onResize(m_size);
fireKeysPress();
}
void X11Window::swapBuffers()

View File

@@ -93,7 +93,6 @@ private:
int m_screen;
Atom m_wmDelete;
std::string m_clipboardText;
std::map<int, Fw::Key> m_keyMap;
#ifndef OPENGL_ES2
GLXContext m_glxContext;