diff --git a/doomsday/libs/gui/include/de/gui/windoweventhandler.h b/doomsday/libs/gui/include/de/gui/windoweventhandler.h index e180365ba1..08287ae9cc 100644 --- a/doomsday/libs/gui/include/de/gui/windoweventhandler.h +++ b/doomsday/libs/gui/include/de/gui/windoweventhandler.h @@ -47,6 +47,8 @@ class LIBGUI_PUBLIC WindowEventHandler : public KeyEventSource, public MouseEven */ DE_DEFINE_AUDIENCE2(FocusChange, void windowFocusChanged(GLWindow &, bool hasFocus)) + enum KeyboardMode { RawKeys, TextInput }; + public: explicit WindowEventHandler(GLWindow *parent); @@ -60,24 +62,17 @@ class LIBGUI_PUBLIC WindowEventHandler : public KeyEventSource, public MouseEven */ void trapMouse(bool trap = true); + void setKeyboardMode(KeyboardMode kbMode); + + KeyboardMode keyboardMode() const; + /** * Determines if the mouse is presently trapped by the canvas. */ bool isMouseTrapped() const; -// // Native events. void handleSDLEvent(const void *); -// void focusInEvent(QFocusEvent *ev); -// void focusOutEvent(QFocusEvent *ev); -// void keyPressEvent(QKeyEvent *ev); -// void keyReleaseEvent(QKeyEvent *ev); -// void mousePressEvent(QMouseEvent *ev); -// void mouseReleaseEvent(QMouseEvent *ev); -// void mouseDoubleClickEvent(QMouseEvent *ev); -// void mouseMoveEvent(QMouseEvent *ev); -// void wheelEvent(QWheelEvent *ev); - private: DE_PRIVATE(d) }; diff --git a/doomsday/libs/gui/src/glwindow.cpp b/doomsday/libs/gui/src/glwindow.cpp index 52b366c461..4cb743382c 100644 --- a/doomsday/libs/gui/src/glwindow.cpp +++ b/doomsday/libs/gui/src/glwindow.cpp @@ -300,7 +300,8 @@ GLWindow::GLWindow() // connect(this, SIGNAL(frameSwapped()), this, SLOT(frameWasSwapped())); d->handler = new WindowEventHandler(this); - + d->handler->setKeyboardMode(WindowEventHandler::RawKeys); + d->pixelRatio = devicePixelRatio(); connect(this, &QWindow::screenChanged, [this](QScreen *scr) { @@ -615,6 +616,11 @@ void GLWindow::handleSDLEvent(const void *ptr) { case SDL_KEYDOWN: case SDL_KEYUP: + case SDL_TEXTINPUT: + case SDL_MOUSEMOTION: + case SDL_MOUSEBUTTONDOWN: + case SDL_MOUSEBUTTONUP: + case SDL_MOUSEWHEEL: d->handler->handleSDLEvent(ptr); break; diff --git a/doomsday/libs/gui/src/guiapp.cpp b/doomsday/libs/gui/src/guiapp.cpp index 167a1595f7..89571d82ef 100644 --- a/doomsday/libs/gui/src/guiapp.cpp +++ b/doomsday/libs/gui/src/guiapp.cpp @@ -64,7 +64,7 @@ DE_PIMPL(GuiApp) SDL_DisplayMode mode; if (SDL_GetCurrentDisplayMode(0, &mode) == 0) { - LOG_GL_MSG("Current display mode refresh rate %d Hz") << mode.refresh_rate; + LOG_GL_MSG("Current display mode refresh rate: %d Hz") << mode.refresh_rate; self().loop().setRate(mode.refresh_rate ? mode.refresh_rate : 60.0); } } @@ -90,6 +90,9 @@ DE_PIMPL(GuiApp) case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONUP: case SDL_MOUSEWHEEL: + case SDL_KEYDOWN: + case SDL_KEYUP: + case SDL_TEXTINPUT: if (window) window->handleSDLEvent(&event); break; } diff --git a/doomsday/libs/gui/src/windoweventhandler.cpp b/doomsday/libs/gui/src/windoweventhandler.cpp index 6a1737c28e..0847b17884 100644 --- a/doomsday/libs/gui/src/windoweventhandler.cpp +++ b/doomsday/libs/gui/src/windoweventhandler.cpp @@ -29,15 +29,16 @@ namespace de { DE_PIMPL(WindowEventHandler) { - GLWindow *window; - bool mouseGrabbed = false; - Vec2i prevMousePos; - Time prevWheelAt; - Vec2i wheelAngleAccum; - int wheelDir[2]; -#if defined (WIN32) - bool altIsDown = false; -#endif + GLWindow * window; + bool mouseGrabbed = false; + KeyboardMode keyboardMode = TextInput; + Vec2i prevMousePos; + Time prevWheelAt; + Vec2i wheelAngleAccum; + int wheelDir[2]; + //#if defined (WIN32) + // bool altIsDown = false; + //#endif Impl(Public *i, GLWindow *parentWindow) : Base(i) @@ -92,47 +93,34 @@ DE_PIMPL(WindowEventHandler) } #endif - void handleKeyEvent(const SDL_KeyboardEvent &ev) + void handleTextInput(const SDL_TextInputEvent &ev) { - //LOG_AS("Canvas"); - -// ev->accept(); - //if (ev->isAutoRepeat()) return; // Ignore repeats, we do our own. - - /* - qDebug() << "Canvas: key press" << ev->key() << QString("0x%1").arg(ev->key(), 0, 16) - << "text:" << ev->text() - << "native:" << ev->nativeVirtualKey() - << "scancode:" << ev->nativeScanCode(); - */ - -#if 0 - // We must track the state of the alt key ourselves as the OS grabs the up event... - if (ev->key() == Qt::Key_Alt) + KeyEvent keyEvent(KeyEvent::Pressed, 0, 0, 0, ev.text); + DE_FOR_PUBLIC_AUDIENCE2(KeyEvent, i) { - if (ev->type() == QEvent::KeyPress) - { - if (altIsDown) return; // Ignore repeat down events(!)? - altIsDown = true; - } - else if (ev->type() == QEvent::KeyRelease) - { - if (!altIsDown) - { - LOG_DEBUG("Ignoring repeat alt up."); - return; // Ignore repeat up events. - } - altIsDown = false; - //LOG_DEBUG("Alt is up."); - } + i->keyEvent(keyEvent); } -#endif + } + + void handleKeyEvent(const SDL_KeyboardEvent &ev) + { + debug("text input active: %i", SDL_IsTextInputActive()); + + const int ddKey = KeyEvent::ddKeyFromSDL(ev.keysym.sym, ev.keysym.scancode); + KeyEvent keyEvent(ev.state == SDL_PRESSED + ? (ev.repeat ? KeyEvent::Repeat : KeyEvent::Pressed) + : KeyEvent::Released, + ddKey, + ev.keysym.sym, + ev.keysym.scancode, + String(), + KeyEvent::modifiersFromSDL(ev.keysym.mod)); DE_FOR_PUBLIC_AUDIENCE2(KeyEvent, i) { - i->keyEvent(KeyEvent()); + i->keyEvent(keyEvent); -/* i->keyEvent(KeyEvent(ev->isAutoRepeat()? KeyEvent::Repeat : + /* i->keyEvent(KeyEvent(ev->isAutoRepeat()? KeyEvent::Repeat : ev->type() == QEvent::KeyPress? KeyEvent::Pressed : KeyEvent::Released, ev->key(), @@ -181,6 +169,29 @@ void WindowEventHandler::trapMouse(bool trap) } } +void WindowEventHandler::setKeyboardMode(KeyboardMode kbMode) +{ + if (d->keyboardMode != kbMode) + { + d->keyboardMode = kbMode; + if (kbMode == TextInput) + { + LOG_INPUT_MSG("Begin text input mode"); + SDL_StartTextInput(); + } + else + { + LOG_INPUT_MSG("End text input mode"); + SDL_StopTextInput(); + } + } +} + +WindowEventHandler::KeyboardMode WindowEventHandler::keyboardMode() const +{ + return d->keyboardMode; +} + bool WindowEventHandler::isMouseTrapped() const { return d->mouseGrabbed; @@ -195,6 +206,10 @@ void WindowEventHandler::handleSDLEvent(const void *ptr) case SDL_KEYUP: d->handleKeyEvent(event->key); break; + + case SDL_TEXTINPUT: + d->handleTextInput(event->text); + break; } } diff --git a/doomsday/tests/test_glsandbox/testwindow.cpp b/doomsday/tests/test_glsandbox/testwindow.cpp index 150e87a94a..284c3659ff 100644 --- a/doomsday/tests/test_glsandbox/testwindow.cpp +++ b/doomsday/tests/test_glsandbox/testwindow.cpp @@ -42,6 +42,7 @@ namespace dgl = de::gl; DE_PIMPL(TestWindow) , DE_OBSERVES(GLWindow, Init) , DE_OBSERVES(GLWindow, Resize) +, DE_OBSERVES(KeyEventSource, KeyEvent) , DE_OBSERVES(Clock, TimeChange) , DE_OBSERVES(Bank, Load) { @@ -92,6 +93,7 @@ DE_PIMPL(TestWindow) self().audienceForInit() += this; self().audienceForResize() += this; + self().eventHandler().audienceForKeyEvent() += this; Clock::get().audienceForTimeChange() += this; uColor = Vec4f(.5f, .75f, .5f, 1); @@ -521,6 +523,29 @@ DE_PIMPL(TestWindow) eraseAtlas = true; } } + + void keyEvent(KeyEvent const &event) + { + debug("sdlkey %x (%s) [%s]", + event.sdlKey(), + event.state() == KeyEvent::Pressed + ? "down" + : event.state() == KeyEvent::Released ? "up" : "repeat", + event.text().c_str()); + + if (event.state() == KeyEvent::Pressed) + { + switch (event.ddKey()) + { + case '1': self().testRenderToTexture(); break; + case '2': self().testDynamicAtlas(); break; + case '3': self().testModel(); break; + case '4': self().loadMD2Model(); break; + case '5': self().loadMD5Model(); break; + default: break; + } + } + } }; TestWindow::TestWindow() : d(new Impl(this))