mirror of
https://github.com/edubart/otclient.git
synced 2025-10-17 04:53:27 +02:00
walk and key event system rework with some regressions
This commit is contained in:
@@ -228,6 +228,8 @@ namespace Fw
|
||||
|
||||
enum InputEventType {
|
||||
NoInputEvent = 0,
|
||||
KeyTextInputEvent,
|
||||
KeyDownInputEvent,
|
||||
KeyPressInputEvent,
|
||||
KeyReleaseInputEvent,
|
||||
MousePressInputEvent,
|
||||
|
@@ -76,10 +76,8 @@ void ConfigManager::setList(const std::string& key, const std::vector<std::strin
|
||||
return;
|
||||
|
||||
OTMLNodePtr child = OTMLNode::create(key, true);
|
||||
for(const std::string& value : list) {
|
||||
for(const std::string& value : list)
|
||||
child->writeIn(value);
|
||||
dump << "insert" << value;
|
||||
}
|
||||
m_confsDoc->addChild(child);
|
||||
}
|
||||
|
||||
|
@@ -26,14 +26,30 @@
|
||||
#include "declarations.h"
|
||||
|
||||
struct InputEvent {
|
||||
InputEvent() {
|
||||
reset();
|
||||
keyboardModifiers = 0;
|
||||
}
|
||||
|
||||
void reset(Fw::InputEventType eventType = Fw::NoInputEvent) {
|
||||
type = eventType;
|
||||
wheelDirection = Fw::MouseNoWheel;
|
||||
mouseButton = Fw::MouseNoButton;
|
||||
keyCode = Fw::KeyUnknown;
|
||||
keyText = "";
|
||||
mouseMoved = Point();
|
||||
wouldFilter = false;
|
||||
};
|
||||
|
||||
Fw::InputEventType type;
|
||||
Fw::MouseWheelDirection wheelDirection;
|
||||
Fw::MouseButton mouseButton;
|
||||
int keyboardModifiers;
|
||||
std::string keyText;
|
||||
Fw::Key keyCode;
|
||||
std::string keyText;
|
||||
int keyboardModifiers;
|
||||
Point mousePos;
|
||||
Point mouseMoved;
|
||||
bool wouldFilter;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@@ -29,7 +29,7 @@ Particle::Particle(const Point& pos, const Size& startSize, const Size& finalSiz
|
||||
m_colors = colors;
|
||||
m_colorsStops = colorsStops;
|
||||
|
||||
m_position = PointF(pos.x, pos.y);
|
||||
m_pos = PointF(pos.x, pos.y);
|
||||
m_startSize = startSize;
|
||||
m_finalSize = finalSize;
|
||||
m_velocity = velocity;
|
||||
@@ -80,18 +80,18 @@ void Particle::updatePosition(double elapsedTime)
|
||||
PointF delta = m_velocity * elapsedTime;
|
||||
delta.y *= -1; // painter orientate Y axis in the inverse direction
|
||||
|
||||
PointF position = m_position + delta;
|
||||
PointF position = m_pos + delta;
|
||||
|
||||
if(m_position != position) {
|
||||
if(m_pos != position) {
|
||||
mustRedraw = true;
|
||||
m_position += delta;
|
||||
m_pos += delta;
|
||||
}
|
||||
|
||||
// update acceleration
|
||||
m_velocity += m_acceleration * elapsedTime;
|
||||
}
|
||||
|
||||
m_rect.move((int)m_position.x - m_size.width() / 2, (int)m_position.y - m_size.height() / 2);
|
||||
m_rect.move((int)m_pos.x - m_size.width() / 2, (int)m_pos.y - m_size.height() / 2);
|
||||
}
|
||||
|
||||
void Particle::updateSize()
|
||||
|
@@ -36,10 +36,10 @@ public:
|
||||
|
||||
bool hasFinished() { return m_finished; }
|
||||
|
||||
PointF getPos() { return m_position; }
|
||||
PointF getPos() { return m_pos; }
|
||||
PointF getVelocity() { return m_velocity; }
|
||||
|
||||
void setPos(const PointF& position) { m_position = position; }
|
||||
void setPos(const PointF& position) { m_pos = position; }
|
||||
void setVelocity(const PointF& velocity) { m_velocity = velocity; }
|
||||
|
||||
private:
|
||||
@@ -51,7 +51,7 @@ private:
|
||||
std::vector<Color> m_colors;
|
||||
std::vector<float> m_colorsStops;
|
||||
TexturePtr m_texture;
|
||||
PointF m_position;
|
||||
PointF m_pos;
|
||||
PointF m_velocity;
|
||||
PointF m_acceleration;
|
||||
Size m_size, m_startSize, m_finalSize;
|
||||
|
@@ -115,7 +115,7 @@ bool AttractionAffector::load(const OTMLNodePtr& node)
|
||||
|
||||
for(const OTMLNodePtr& childNode : node->children()) {
|
||||
if(childNode->tag() == "position")
|
||||
m_position = childNode->value<Point>();
|
||||
m_pos = childNode->value<Point>();
|
||||
else if(childNode->tag() == "acceleration")
|
||||
m_acceleration = childNode->value<float>();
|
||||
else if(childNode->tag() == "velocity-reduction-percent")
|
||||
@@ -132,7 +132,7 @@ void AttractionAffector::updateParticle(const ParticlePtr& particle, double elap
|
||||
return;
|
||||
|
||||
PointF pPosition = particle->getPos();
|
||||
PointF d = PointF(m_position.x - pPosition.x, pPosition.y - m_position.y);
|
||||
PointF d = PointF(m_pos.x - pPosition.x, pPosition.y - m_pos.y);
|
||||
if(d.length() == 0)
|
||||
return;
|
||||
|
||||
|
@@ -57,7 +57,7 @@ public:
|
||||
void updateParticle(const ParticlePtr& particle, double elapsedTime);
|
||||
|
||||
private:
|
||||
Point m_position;
|
||||
Point m_pos;
|
||||
float m_acceleration, m_reduction;
|
||||
bool m_repelish;
|
||||
};
|
||||
|
@@ -31,7 +31,7 @@ ParticleEmitter::ParticleEmitter(const ParticleSystemPtr& parent)
|
||||
{
|
||||
m_parent = parent;
|
||||
|
||||
m_position = Point(0, 0);
|
||||
m_pos = Point(0, 0);
|
||||
m_duration = -1;
|
||||
m_delay = 0;
|
||||
m_burstRate = 1; m_burstCount = 32;
|
||||
@@ -65,7 +65,7 @@ bool ParticleEmitter::load(const OTMLNodePtr& node)
|
||||
for(const OTMLNodePtr& childNode : node->children()) {
|
||||
// self related
|
||||
if(childNode->tag() == "position")
|
||||
m_position = childNode->value<Point>();
|
||||
m_pos = childNode->value<Point>();
|
||||
else if(childNode->tag() == "duration")
|
||||
m_duration = childNode->value<float>();
|
||||
else if(childNode->tag() == "delay")
|
||||
@@ -199,7 +199,7 @@ void ParticleEmitter::update(double elapsedTime)
|
||||
float pRadius = Fw::randomRange(m_pMinPositionRadius, m_pMaxPositionRadius);
|
||||
float pAngle = Fw::randomRange(m_pMinPositionAngle, m_pMaxPositionAngle);
|
||||
|
||||
Point pPosition = m_position + Point(pRadius * cos(pAngle), pRadius * sin(pAngle));
|
||||
Point pPosition = m_pos + Point(pRadius * cos(pAngle), pRadius * sin(pAngle));
|
||||
|
||||
for(int p = 0; p < m_burstCount; ++p) {
|
||||
|
||||
|
@@ -44,7 +44,7 @@ private:
|
||||
ParticleSystemWeakPtr m_parent;
|
||||
|
||||
// self related
|
||||
Point m_position;
|
||||
Point m_pos;
|
||||
float m_duration, m_delay;
|
||||
double m_elapsedTime;
|
||||
bool m_finished, m_active;
|
||||
|
@@ -294,12 +294,12 @@ void Application::registerLuaFunctions()
|
||||
g_lua.bindClassMemberFunction<UIBoxLayout>("setFitChildren", &UIBoxLayout::setFitChildren);
|
||||
|
||||
// UIVerticalLayout
|
||||
g_lua.registerClass<UIVerticalLayout, UILayout>();
|
||||
g_lua.registerClass<UIVerticalLayout, UIBoxLayout>();
|
||||
g_lua.bindClassStaticFunction<UIVerticalLayout>("create", [](UIWidgetPtr parent){ return UIVerticalLayoutPtr(new UIVerticalLayout(parent)); } );
|
||||
g_lua.bindClassMemberFunction<UIVerticalLayout>("setAlignBottom", &UIVerticalLayout::setAlignBottom);
|
||||
|
||||
// UIHorizontalLayout
|
||||
g_lua.registerClass<UIHorizontalLayout, UILayout>();
|
||||
g_lua.registerClass<UIHorizontalLayout, UIBoxLayout>();
|
||||
g_lua.bindClassStaticFunction<UIHorizontalLayout>("create", [](UIWidgetPtr parent){ return UIHorizontalLayoutPtr(new UIHorizontalLayout(parent)); } );
|
||||
g_lua.bindClassMemberFunction<UIHorizontalLayout>("setAlignRight", &UIHorizontalLayout::setAlignRight);
|
||||
|
||||
@@ -404,6 +404,7 @@ void Application::registerLuaFunctions()
|
||||
g_lua.bindClassStaticFunction("g_window", "getY", std::bind(&PlatformWindow::getY, &g_window));
|
||||
g_lua.bindClassStaticFunction("g_window", "getMousePos", std::bind(&PlatformWindow::getMousePos, &g_window));
|
||||
g_lua.bindClassStaticFunction("g_window", "getKeyboardModifiers", std::bind(&PlatformWindow::getKeyboardModifiers, &g_window));
|
||||
g_lua.bindClassStaticFunction("g_window", "isKeyPressed", std::bind(&PlatformWindow::isKeyPressed, &g_window, _1));
|
||||
g_lua.bindClassStaticFunction("g_window", "isVisible", std::bind(&PlatformWindow::isVisible, &g_window));
|
||||
g_lua.bindClassStaticFunction("g_window", "isFullscreen", std::bind(&PlatformWindow::isFullscreen, &g_window));
|
||||
g_lua.bindClassStaticFunction("g_window", "isMaximized", std::bind(&PlatformWindow::isMaximized, &g_window));
|
||||
|
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
|
@@ -82,7 +82,6 @@ private:
|
||||
HGLRC m_glContext;
|
||||
bool m_maximized;
|
||||
Size m_minimumSize;
|
||||
std::map<int, Fw::Key> m_keyMap;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@@ -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()
|
||||
|
@@ -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;
|
||||
|
@@ -389,6 +389,8 @@ void UILineEdit::onStyleApply(const std::string& styleName, const OTMLNodePtr& s
|
||||
setTextHorizontalMargin(node->value<int>());
|
||||
else if(node->tag() == "always-active")
|
||||
setAlwaysActive(node->value<bool>());
|
||||
//else if(node->tag() == "disable-arrow-navitation")
|
||||
// setArrowNavigation(node->value<bool>());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -409,34 +411,41 @@ void UILineEdit::onFocusChange(bool focused, Fw::FocusReason reason)
|
||||
UIWidget::onFocusChange(focused, reason);
|
||||
}
|
||||
|
||||
bool UILineEdit::onKeyPress(uchar keyCode, std::string keyText, int keyboardModifiers)
|
||||
bool UILineEdit::onKeyPress(uchar keyCode, int keyboardModifiers, bool wouldFilter)
|
||||
{
|
||||
if(UIWidget::onKeyPress(keyCode, keyText, keyboardModifiers))
|
||||
if(UIWidget::onKeyPress(keyCode, keyboardModifiers, wouldFilter))
|
||||
return true;
|
||||
|
||||
if(keyCode == Fw::KeyDelete) // erase right character
|
||||
removeCharacter(true);
|
||||
else if(keyCode == Fw::KeyBackspace) // erase left character {
|
||||
removeCharacter(false);
|
||||
else if(keyCode == Fw::KeyRight) // move cursor right
|
||||
moveCursor(true);
|
||||
else if(keyCode == Fw::KeyLeft) // move cursor left
|
||||
moveCursor(false);
|
||||
else if(keyCode == Fw::KeyHome) // move cursor to first character
|
||||
setCursorPos(0);
|
||||
else if(keyCode == Fw::KeyEnd) // move cursor to last character
|
||||
setCursorPos(m_text.length());
|
||||
else if(keyCode == Fw::KeyV && keyboardModifiers == Fw::KeyboardCtrlModifier)
|
||||
appendText(g_window.getClipboardText());
|
||||
else if(keyCode == Fw::KeyTab) {
|
||||
if(!m_alwaysActive) {
|
||||
if(UIWidgetPtr parent = getParent())
|
||||
parent->focusNextChild(Fw::TabFocusReason);
|
||||
}
|
||||
} else if(!keyText.empty() && (keyboardModifiers == Fw::KeyboardNoModifier || keyboardModifiers == Fw::KeyboardShiftModifier))
|
||||
appendText(keyText);
|
||||
else
|
||||
return false;
|
||||
if(!wouldFilter) {
|
||||
if(keyCode == Fw::KeyDelete) // erase right character
|
||||
removeCharacter(true);
|
||||
else if(keyCode == Fw::KeyBackspace) // erase left character {
|
||||
removeCharacter(false);
|
||||
else if(keyCode == Fw::KeyRight) // move cursor right
|
||||
moveCursor(true);
|
||||
else if(keyCode == Fw::KeyLeft) // move cursor left
|
||||
moveCursor(false);
|
||||
else if(keyCode == Fw::KeyHome) // move cursor to first character
|
||||
setCursorPos(0);
|
||||
else if(keyCode == Fw::KeyEnd) // move cursor to last character
|
||||
setCursorPos(m_text.length());
|
||||
else if(keyCode == Fw::KeyV && keyboardModifiers == Fw::KeyboardCtrlModifier)
|
||||
appendText(g_window.getClipboardText());
|
||||
else if(keyCode == Fw::KeyTab) {
|
||||
if(!m_alwaysActive) {
|
||||
if(UIWidgetPtr parent = getParent())
|
||||
parent->focusNextChild(Fw::TabFocusReason);
|
||||
}
|
||||
} else
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UILineEdit::onKeyText(const std::string& keyText)
|
||||
{
|
||||
appendText(keyText);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@@ -61,7 +61,8 @@ protected:
|
||||
virtual void onStyleApply(const std::string& styleName, const OTMLNodePtr& styleNode);
|
||||
virtual void onGeometryChange(const Rect& oldRect, const Rect& newRect);
|
||||
virtual void onFocusChange(bool focused, Fw::FocusReason reason);
|
||||
virtual bool onKeyPress(uchar keyCode, std::string keyText, int keyboardModifiers);
|
||||
virtual bool onKeyText(const std::string& keyText);
|
||||
virtual bool onKeyPress(uchar keyCode, int keyboardModifiers, bool wouldFilter);
|
||||
virtual bool onMousePress(const Point& mousePos, Fw::MouseButton button);
|
||||
|
||||
private:
|
||||
|
@@ -59,11 +59,17 @@ void UIManager::inputEvent(const InputEvent& event)
|
||||
{
|
||||
m_isOnInputEvent = true;
|
||||
switch(event.type) {
|
||||
case Fw::KeyTextInputEvent:
|
||||
m_keyboardReceiver->propagateOnKeyText(event.keyText);
|
||||
break;
|
||||
case Fw::KeyDownInputEvent:
|
||||
m_keyboardReceiver->propagateOnKeyDown(event.keyCode, event.keyboardModifiers);
|
||||
break;
|
||||
case Fw::KeyPressInputEvent:
|
||||
m_keyboardReceiver->propagateOnKeyPress(event.keyCode, event.keyText, event.keyboardModifiers);
|
||||
m_keyboardReceiver->propagateOnKeyPress(event.keyCode, event.keyboardModifiers, event.wouldFilter);
|
||||
break;
|
||||
case Fw::KeyReleaseInputEvent:
|
||||
m_keyboardReceiver->propagateOnKeyRelease(event.keyCode, event.keyText, event.keyboardModifiers);
|
||||
m_keyboardReceiver->propagateOnKeyRelease(event.keyCode, event.keyboardModifiers);
|
||||
break;
|
||||
case Fw::MousePressInputEvent:
|
||||
m_keyboardReceiver->propagateOnMousePress(event.mousePos, event.mouseButton);
|
||||
|
@@ -1053,14 +1053,24 @@ void UIWidget::onHoverChange(bool hovered)
|
||||
g_ui.getRootWidget()->updateState(Fw::HoverState);
|
||||
}
|
||||
|
||||
bool UIWidget::onKeyPress(uchar keyCode, std::string keyText, int keyboardModifiers)
|
||||
bool UIWidget::onKeyText(const std::string& keyText)
|
||||
{
|
||||
return callLuaField<bool>("onKeyPress", keyCode, keyText, keyboardModifiers);
|
||||
return callLuaField<bool>("onKeyText", keyText);
|
||||
}
|
||||
|
||||
bool UIWidget::onKeyRelease(uchar keyCode, std::string keyText, int keyboardModifiers)
|
||||
bool UIWidget::onKeyDown(uchar keyCode, int keyboardModifiers)
|
||||
{
|
||||
return callLuaField<bool>("onKeyRelease", keyCode, keyText, keyboardModifiers);
|
||||
return callLuaField<bool>("onKeyDown", keyCode, keyboardModifiers);
|
||||
}
|
||||
|
||||
bool UIWidget::onKeyPress(uchar keyCode, int keyboardModifiers, bool wouldFilter)
|
||||
{
|
||||
return callLuaField<bool>("onKeyPress", keyCode, keyboardModifiers, wouldFilter);
|
||||
}
|
||||
|
||||
bool UIWidget::onKeyRelease(uchar keyCode, int keyboardModifiers)
|
||||
{
|
||||
return callLuaField<bool>("onKeyRelease", keyCode, keyboardModifiers);
|
||||
}
|
||||
|
||||
bool UIWidget::onMousePress(const Point& mousePos, Fw::MouseButton button)
|
||||
@@ -1086,7 +1096,7 @@ bool UIWidget::onMouseWheel(const Point& mousePos, Fw::MouseWheelDirection direc
|
||||
return callLuaField<bool>("onMouseWheel", mousePos, direction);
|
||||
}
|
||||
|
||||
bool UIWidget::propagateOnKeyPress(uchar keyCode, std::string keyText, int keyboardModifiers)
|
||||
bool UIWidget::propagateOnKeyText(const std::string& keyText)
|
||||
{
|
||||
// do a backup of children list, because it may change while looping it
|
||||
UIWidgetList children;
|
||||
@@ -1101,14 +1111,58 @@ bool UIWidget::propagateOnKeyPress(uchar keyCode, std::string keyText, int keybo
|
||||
}
|
||||
|
||||
for(const UIWidgetPtr& child : children) {
|
||||
if(child->propagateOnKeyPress(keyCode, keyText, keyboardModifiers))
|
||||
if(child->propagateOnKeyText(keyText))
|
||||
return true;
|
||||
}
|
||||
|
||||
return onKeyPress(keyCode, keyText, keyboardModifiers);
|
||||
return onKeyText(keyText);
|
||||
}
|
||||
|
||||
bool UIWidget::propagateOnKeyRelease(uchar keyCode, std::string keyText, int keyboardModifiers)
|
||||
bool UIWidget::propagateOnKeyDown(uchar keyCode, int keyboardModifiers)
|
||||
{
|
||||
// do a backup of children list, because it may change while looping it
|
||||
UIWidgetList children;
|
||||
for(const UIWidgetPtr& child : m_children) {
|
||||
// events on hidden or disabled widgets are discarded
|
||||
if(!child->isExplicitlyEnabled() || !child->isExplicitlyVisible())
|
||||
continue;
|
||||
|
||||
// key events go only to containers or focused child
|
||||
if(child->isFocused())
|
||||
children.push_back(child);
|
||||
}
|
||||
|
||||
for(const UIWidgetPtr& child : children) {
|
||||
if(child->propagateOnKeyDown(keyCode, keyboardModifiers))
|
||||
return true;
|
||||
}
|
||||
|
||||
return onKeyDown(keyCode, keyboardModifiers);
|
||||
}
|
||||
|
||||
bool UIWidget::propagateOnKeyPress(uchar keyCode, int keyboardModifiers, bool wouldFilter)
|
||||
{
|
||||
// do a backup of children list, because it may change while looping it
|
||||
UIWidgetList children;
|
||||
for(const UIWidgetPtr& child : m_children) {
|
||||
// events on hidden or disabled widgets are discarded
|
||||
if(!child->isExplicitlyEnabled() || !child->isExplicitlyVisible())
|
||||
continue;
|
||||
|
||||
// key events go only to containers or focused child
|
||||
if(child->isFocused())
|
||||
children.push_back(child);
|
||||
}
|
||||
|
||||
for(const UIWidgetPtr& child : children) {
|
||||
if(child->propagateOnKeyPress(keyCode, keyboardModifiers, wouldFilter))
|
||||
return true;
|
||||
}
|
||||
|
||||
return onKeyPress(keyCode, keyboardModifiers, wouldFilter);
|
||||
}
|
||||
|
||||
bool UIWidget::propagateOnKeyRelease(uchar keyCode, int keyboardModifiers)
|
||||
{
|
||||
// do a backup of children list, because it may change while looping it
|
||||
UIWidgetList children;
|
||||
@@ -1123,11 +1177,11 @@ bool UIWidget::propagateOnKeyRelease(uchar keyCode, std::string keyText, int key
|
||||
}
|
||||
|
||||
for(const UIWidgetPtr& child : children) {
|
||||
if(child->propagateOnKeyRelease(keyCode, keyText, keyboardModifiers))
|
||||
if(child->propagateOnKeyRelease(keyCode, keyboardModifiers))
|
||||
return true;
|
||||
}
|
||||
|
||||
return onKeyRelease(keyCode, keyText, keyboardModifiers);
|
||||
return onKeyRelease(keyCode, keyboardModifiers);
|
||||
}
|
||||
|
||||
bool UIWidget::propagateOnMousePress(const Point& mousePos, Fw::MouseButton button)
|
||||
|
@@ -161,15 +161,19 @@ protected:
|
||||
virtual void onGeometryChange(const Rect& oldRect, const Rect& newRect);
|
||||
virtual void onFocusChange(bool focused, Fw::FocusReason reason);
|
||||
virtual void onHoverChange(bool hovered);
|
||||
virtual bool onKeyPress(uchar keyCode, std::string keyText, int keyboardModifiers);
|
||||
virtual bool onKeyRelease(uchar keyCode, std::string keyText, int keyboardModifiers);
|
||||
virtual bool onKeyText(const std::string& keyText);
|
||||
virtual bool onKeyDown(uchar keyCode, int keyboardModifiers);
|
||||
virtual bool onKeyPress(uchar keyCode, int keyboardModifiers, bool wouldFilter);
|
||||
virtual bool onKeyRelease(uchar keyCode, int keyboardModifiers);
|
||||
virtual bool onMousePress(const Point& mousePos, Fw::MouseButton button);
|
||||
virtual void onMouseRelease(const Point& mousePos, Fw::MouseButton button);
|
||||
virtual bool onMouseMove(const Point& mousePos, const Point& mouseMoved);
|
||||
virtual bool onMouseWheel(const Point& mousePos, Fw::MouseWheelDirection direction);
|
||||
|
||||
bool propagateOnKeyPress(uchar keyCode, std::string keyText, int keyboardModifiers);
|
||||
bool propagateOnKeyRelease(uchar keyCode, std::string keyText, int keyboardModifiers);
|
||||
bool propagateOnKeyText(const std::string& keyText);
|
||||
bool propagateOnKeyDown(uchar keyCode, int keyboardModifiers);
|
||||
bool propagateOnKeyPress(uchar keyCode, int keyboardModifiers, bool wouldFilter);
|
||||
bool propagateOnKeyRelease(uchar keyCode, int keyboardModifiers);
|
||||
bool propagateOnMousePress(const Point& mousePos, Fw::MouseButton button);
|
||||
void propagateOnMouseRelease(const Point& mousePos, Fw::MouseButton button);
|
||||
bool propagateOnMouseMove(const Point& mousePos, const Point& mouseMoved);
|
||||
|
Reference in New Issue
Block a user