From 8915ecd23d1196142f856d72dc8713a3073e45be Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Wed, 22 Mar 2017 09:17:30 -0700 Subject: [PATCH 1/2] compile time option to switch from touch to mouse events for web tablet --- interface/src/ui/overlays/Web3DOverlay.cpp | 48 ++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/interface/src/ui/overlays/Web3DOverlay.cpp b/interface/src/ui/overlays/Web3DOverlay.cpp index ede630d4ad..97c736cc8e 100644 --- a/interface/src/ui/overlays/Web3DOverlay.cpp +++ b/interface/src/ui/overlays/Web3DOverlay.cpp @@ -340,6 +340,52 @@ void Web3DOverlay::setProxyWindow(QWindow* proxyWindow) { _webSurface->setProxyWindow(proxyWindow); } +#define USE_MOUSE_EVENTS + +#ifdef USE_MOUSE_EVENTS +void Web3DOverlay::handlePointerEvent(const PointerEvent& event) { + if (!_webSurface) { + return; + } + + glm::vec2 windowPos = event.getPos2D() * (METERS_TO_INCHES * _dpi); + QPointF windowPoint(windowPos.x, windowPos.y); + + if (event.getType() == PointerEvent::Press) { + this->_pressed = true; + } else if (event.getType() == PointerEvent::Release) { + this->_pressed = false; + } + + + Qt::MouseButtons buttons = Qt::NoButton; + if (event.getButtons() & PointerEvent::PrimaryButton) { + buttons |= Qt::LeftButton; + } + + QEvent::Type type; + Qt::MouseButton button = Qt::NoButton; + if (event.getButton() == PointerEvent::PrimaryButton) { + button = Qt::LeftButton; + } + switch (event.getType()) { + case PointerEvent::Press: + type = QEvent::MouseButtonPress; + break; + case PointerEvent::Release: + type = QEvent::MouseButtonRelease; + break; + case PointerEvent::Move: + default: + type = QEvent::MouseMove; + break; + } + + QMouseEvent* mouseEvent = new QMouseEvent(type, windowPoint, windowPoint, windowPoint, button, buttons, Qt::NoModifier); + QCoreApplication::postEvent(_webSurface->getWindow(), mouseEvent); +} + +#else void Web3DOverlay::handlePointerEvent(const PointerEvent& event) { if (!_webSurface) { return; @@ -395,6 +441,8 @@ void Web3DOverlay::handlePointerEvent(const PointerEvent& event) { QCoreApplication::postEvent(_webSurface->getWindow(), touchEvent); } +#endif + void Web3DOverlay::setProperties(const QVariantMap& properties) { Billboard3DOverlay::setProperties(properties); From bab9890fea046e8c7165b686fbac1207b215d50a Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Thu, 23 Mar 2017 11:02:17 -0700 Subject: [PATCH 2/2] Added inputMode property to Web3DOverlay. This allows user to switch between Touch messages and Mouse messages. Added a sliderTestMain.js script which demonstrates this behavior. --- interface/src/ui/overlays/Web3DOverlay.cpp | 141 ++++++++-------- interface/src/ui/overlays/Web3DOverlay.h | 8 + libraries/shared/src/PointerEvent.cpp | 28 +++- libraries/shared/src/PointerEvent.h | 5 +- scripts/developer/tests/sliderTest.html | 157 ++++++++++++++++++ scripts/developer/tests/sliderTestMain.js | 35 ++++ .../system/controllers/handControllerGrab.js | 6 +- 7 files changed, 305 insertions(+), 75 deletions(-) create mode 100644 scripts/developer/tests/sliderTest.html create mode 100644 scripts/developer/tests/sliderTestMain.js diff --git a/interface/src/ui/overlays/Web3DOverlay.cpp b/interface/src/ui/overlays/Web3DOverlay.cpp index 97c736cc8e..1cf40d282d 100644 --- a/interface/src/ui/overlays/Web3DOverlay.cpp +++ b/interface/src/ui/overlays/Web3DOverlay.cpp @@ -232,10 +232,7 @@ void Web3DOverlay::render(RenderArgs* args) { std::weak_ptr weakSelf = std::dynamic_pointer_cast(qApp->getOverlays().getOverlay(selfOverlayID)); auto forwardPointerEvent = [=](OverlayID overlayID, const PointerEvent& event) { auto self = weakSelf.lock(); - if (!self) { - return; - } - if (overlayID == selfOverlayID) { + if (self && overlayID == selfOverlayID) { self->handlePointerEvent(event); } }; @@ -249,22 +246,9 @@ void Web3DOverlay::render(RenderArgs* args) { return; } if (self->_pressed && overlayID == selfOverlayID) { - // If the user mouses off the overlay while the button is down, simulate a touch end. - QTouchEvent::TouchPoint point; - point.setId(event.getID()); - point.setState(Qt::TouchPointReleased); - glm::vec2 windowPos = event.getPos2D() * (METERS_TO_INCHES * _dpi); - QPointF windowPoint(windowPos.x, windowPos.y); - point.setScenePos(windowPoint); - point.setPos(windowPoint); - QList touchPoints; - touchPoints.push_back(point); - QTouchEvent* touchEvent = new QTouchEvent(QEvent::TouchEnd, nullptr, Qt::NoModifier, Qt::TouchPointReleased, - touchPoints); - touchEvent->setWindow(self->_webSurface->getWindow()); - touchEvent->setDevice(&_touchDevice); - touchEvent->setTarget(self->_webSurface->getRootItem()); - QCoreApplication::postEvent(self->_webSurface->getWindow(), touchEvent); + PointerEvent endEvent(PointerEvent::Release, event.getID(), event.getPos2D(), event.getPos3D(), event.getNormal(), event.getDirection(), + event.getButton(), event.getButtons(), event.getKeyboardModifiers()); + forwardPointerEvent(overlayID, event); } }, Qt::DirectConnection); @@ -340,53 +324,15 @@ void Web3DOverlay::setProxyWindow(QWindow* proxyWindow) { _webSurface->setProxyWindow(proxyWindow); } -#define USE_MOUSE_EVENTS - -#ifdef USE_MOUSE_EVENTS void Web3DOverlay::handlePointerEvent(const PointerEvent& event) { - if (!_webSurface) { - return; + if (_inputMode == Touch) { + handlePointerEventAsTouch(event); + } else { + handlePointerEventAsMouse(event); } - - glm::vec2 windowPos = event.getPos2D() * (METERS_TO_INCHES * _dpi); - QPointF windowPoint(windowPos.x, windowPos.y); - - if (event.getType() == PointerEvent::Press) { - this->_pressed = true; - } else if (event.getType() == PointerEvent::Release) { - this->_pressed = false; - } - - - Qt::MouseButtons buttons = Qt::NoButton; - if (event.getButtons() & PointerEvent::PrimaryButton) { - buttons |= Qt::LeftButton; - } - - QEvent::Type type; - Qt::MouseButton button = Qt::NoButton; - if (event.getButton() == PointerEvent::PrimaryButton) { - button = Qt::LeftButton; - } - switch (event.getType()) { - case PointerEvent::Press: - type = QEvent::MouseButtonPress; - break; - case PointerEvent::Release: - type = QEvent::MouseButtonRelease; - break; - case PointerEvent::Move: - default: - type = QEvent::MouseMove; - break; - } - - QMouseEvent* mouseEvent = new QMouseEvent(type, windowPoint, windowPoint, windowPoint, button, buttons, Qt::NoModifier); - QCoreApplication::postEvent(_webSurface->getWindow(), mouseEvent); } -#else -void Web3DOverlay::handlePointerEvent(const PointerEvent& event) { +void Web3DOverlay::handlePointerEventAsTouch(const PointerEvent& event) { if (!_webSurface) { return; } @@ -394,16 +340,16 @@ void Web3DOverlay::handlePointerEvent(const PointerEvent& event) { glm::vec2 windowPos = event.getPos2D() * (METERS_TO_INCHES * _dpi); QPointF windowPoint(windowPos.x, windowPos.y); - if (event.getType() == PointerEvent::Move) { + if (event.getButtons() == PointerEvent::NoButtons && event.getType() == PointerEvent::Move) { // Forward a mouse move event to the Web surface. - QMouseEvent* mouseEvent = new QMouseEvent(QEvent::MouseMove, windowPoint, windowPoint, windowPoint, Qt::NoButton, - Qt::NoButton, Qt::NoModifier); + QMouseEvent* mouseEvent = new QMouseEvent(QEvent::MouseMove, windowPoint, windowPoint, windowPoint, Qt::NoButton, Qt::NoButton, Qt::NoModifier); QCoreApplication::postEvent(_webSurface->getWindow(), mouseEvent); + return; } - if (event.getType() == PointerEvent::Press) { + if (event.getType() == PointerEvent::Press && event.getButton() == PointerEvent::PrimaryButton) { this->_pressed = true; - } else if (event.getType() == PointerEvent::Release) { + } else if (event.getType() == PointerEvent::Release && event.getButton() == PointerEvent::PrimaryButton) { this->_pressed = false; } @@ -441,8 +387,47 @@ void Web3DOverlay::handlePointerEvent(const PointerEvent& event) { QCoreApplication::postEvent(_webSurface->getWindow(), touchEvent); } -#endif +void Web3DOverlay::handlePointerEventAsMouse(const PointerEvent& event) { + if (!_webSurface) { + return; + } + + glm::vec2 windowPos = event.getPos2D() * (METERS_TO_INCHES * _dpi); + QPointF windowPoint(windowPos.x, windowPos.y); + + if (event.getType() == PointerEvent::Press) { + this->_pressed = true; + } else if (event.getType() == PointerEvent::Release) { + this->_pressed = false; + } + + Qt::MouseButtons buttons = Qt::NoButton; + if (event.getButtons() & PointerEvent::PrimaryButton) { + buttons |= Qt::LeftButton; + } + + QEvent::Type type; + Qt::MouseButton button = Qt::NoButton; + if (event.getButton() == PointerEvent::PrimaryButton) { + button = Qt::LeftButton; + } + switch (event.getType()) { + case PointerEvent::Press: + type = QEvent::MouseButtonPress; + break; + case PointerEvent::Release: + type = QEvent::MouseButtonRelease; + break; + case PointerEvent::Move: + default: + type = QEvent::MouseMove; + break; + } + + QMouseEvent* mouseEvent = new QMouseEvent(type, windowPoint, windowPoint, windowPoint, button, buttons, Qt::NoModifier); + QCoreApplication::postEvent(_webSurface->getWindow(), mouseEvent); +} void Web3DOverlay::setProperties(const QVariantMap& properties) { Billboard3DOverlay::setProperties(properties); @@ -486,6 +471,16 @@ void Web3DOverlay::setProperties(const QVariantMap& properties) { if (showKeyboardFocusHighlight.isValid()) { _showKeyboardFocusHighlight = showKeyboardFocusHighlight.toBool(); } + + auto inputModeValue = properties["inputMode"]; + if (inputModeValue.isValid()) { + QString inputModeStr = inputModeValue.toString(); + if (inputModeStr == "Mouse") { + _inputMode = Mouse; + } else { + _inputMode = Touch; + } + } } QVariant Web3DOverlay::getProperty(const QString& property) { @@ -507,6 +502,14 @@ QVariant Web3DOverlay::getProperty(const QString& property) { if (property == "showKeyboardFocusHighlight") { return _showKeyboardFocusHighlight; } + + if (property == "inputMode") { + if (_inputMode == Mouse) { + return QVariant("Mouse"); + } else { + return QVariant("Touch"); + } + } return Billboard3DOverlay::getProperty(property); } diff --git a/interface/src/ui/overlays/Web3DOverlay.h b/interface/src/ui/overlays/Web3DOverlay.h index e71cac2452..6a35dec96d 100644 --- a/interface/src/ui/overlays/Web3DOverlay.h +++ b/interface/src/ui/overlays/Web3DOverlay.h @@ -40,6 +40,8 @@ public: QObject* getEventHandler(); void setProxyWindow(QWindow* proxyWindow); void handlePointerEvent(const PointerEvent& event); + void handlePointerEventAsTouch(const PointerEvent& event); + void handlePointerEventAsMouse(const PointerEvent& event); // setters void setURL(const QString& url); @@ -55,6 +57,11 @@ public: virtual Web3DOverlay* createClone() const override; + enum InputMode { + Touch, + Mouse + }; + public slots: void emitScriptEvent(const QVariant& scriptMessage); @@ -63,6 +70,7 @@ signals: void webEventReceived(const QVariant& message); private: + InputMode _inputMode { Touch }; QSharedPointer _webSurface; QMetaObject::Connection _connection; gpu::TexturePointer _texture; diff --git a/libraries/shared/src/PointerEvent.cpp b/libraries/shared/src/PointerEvent.cpp index 1a64a5ddb1..7ec5e78b9f 100644 --- a/libraries/shared/src/PointerEvent.cpp +++ b/libraries/shared/src/PointerEvent.cpp @@ -143,7 +143,7 @@ void PointerEvent::fromScriptValue(const QScriptValue& object, PointerEvent& eve } QScriptValue id = object.property("id"); - event._id = type.isNumber() ? (uint32_t)type.toNumber() : 0; + event._id = id.isNumber() ? (uint32_t)id.toNumber() : 0; glm::vec2 pos2D; vec2FromScriptValue(object.property("pos2D"), event._pos2D); @@ -158,7 +158,8 @@ void PointerEvent::fromScriptValue(const QScriptValue& object, PointerEvent& eve vec3FromScriptValue(object.property("direction"), event._direction); QScriptValue button = object.property("button"); - QString buttonStr = type.isString() ? type.toString() : "NoButtons"; + QString buttonStr = type.isString() ? button.toString() : "NoButtons"; + if (buttonStr == "Primary") { event._button = PrimaryButton; } else if (buttonStr == "Secondary") { @@ -186,3 +187,26 @@ void PointerEvent::fromScriptValue(const QScriptValue& object, PointerEvent& eve event._keyboardModifiers = (Qt::KeyboardModifiers)(object.property("keyboardModifiers").toUInt32()); } } + +static const char* typeToStringMap[PointerEvent::NumEventTypes] = { "Press", "DoublePress", "Release", "Move" }; +static const char* buttonsToStringMap[8] = { + "NoButtons", + "PrimaryButton", + "SecondaryButton", + "PrimaryButton | SecondaryButton", + "TertiaryButton", + "PrimaryButton | TertiaryButton", + "SecondaryButton | TertiaryButton", + "PrimaryButton | SecondaryButton | TertiaryButton", +}; + +QDebug& operator<<(QDebug& dbg, const PointerEvent& p) { + dbg.nospace() << "PointerEvent, type = " << typeToStringMap[p.getType()] << ", id = " << p.getID(); + dbg.nospace() << ", pos2D = (" << p.getPos2D().x << ", " << p.getPos2D().y; + dbg.nospace() << "), pos3D = (" << p.getPos3D().x << ", " << p.getPos3D().y << ", " << p.getPos3D().z; + dbg.nospace() << "), normal = (" << p.getNormal().x << ", " << p.getNormal().y << ", " << p.getNormal().z; + dbg.nospace() << "), dir = (" << p.getDirection().x << ", " << p.getDirection().y << ", " << p.getDirection().z; + dbg.nospace() << "), button = " << buttonsToStringMap[p.getButton()] << " " << (int)p.getButton(); + dbg.nospace() << ", buttons = " << buttonsToStringMap[p.getButtons()]; + return dbg; +} diff --git a/libraries/shared/src/PointerEvent.h b/libraries/shared/src/PointerEvent.h index 4c00ba3e69..cdea0aa3ed 100644 --- a/libraries/shared/src/PointerEvent.h +++ b/libraries/shared/src/PointerEvent.h @@ -31,7 +31,8 @@ public: Press, // A button has just been pressed DoublePress, // A button has just been double pressed Release, // A button has just been released - Move // The pointer has just moved + Move, // The pointer has just moved + NumEventTypes }; PointerEvent(); @@ -68,6 +69,8 @@ private: Qt::KeyboardModifiers _keyboardModifiers; // set of keys held when event was generated }; +QDebug& operator<<(QDebug& dbg, const PointerEvent& p); + Q_DECLARE_METATYPE(PointerEvent) #endif // hifi_PointerEvent_h diff --git a/scripts/developer/tests/sliderTest.html b/scripts/developer/tests/sliderTest.html new file mode 100644 index 0000000000..a672cfeaf8 --- /dev/null +++ b/scripts/developer/tests/sliderTest.html @@ -0,0 +1,157 @@ + + + + Slider Test + + + + + + + + + +
+

Slider Test

+
+
+

Native Input Range Slider

+

+ +

+

Bootstrap Slider

+

+ +

+
+ + + + + + + \ No newline at end of file diff --git a/scripts/developer/tests/sliderTestMain.js b/scripts/developer/tests/sliderTestMain.js new file mode 100644 index 0000000000..22bf4fa911 --- /dev/null +++ b/scripts/developer/tests/sliderTestMain.js @@ -0,0 +1,35 @@ +(function () { + var HTML_URL = Script.resolvePath("sliderTest.html"); + var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + var button = tablet.addButton({ + text: "SLIDER" + }); + + function onClicked() { + tablet.gotoWebScreen(HTML_URL); + } + + button.clicked.connect(onClicked); + + var onSliderTestScreen = false; + function onScreenChanged(type, url) { + if (type === "Web" && url === HTML_URL) { + // when switching to the slider page, change inputMode to "Mouse", this should make the sliders work. + onSliderTestScreen = true; + Overlays.editOverlay(HMD.tabletScreenID, { inputMode: "Mouse" }); + } else if (onSliderTestScreen) { + // when switching off of the slider page, change inputMode to back to "Touch". + onSliderTestScreen = false; + Overlays.editOverlay(HMD.tabletScreenID, { inputMode: "Touch" }); + } + } + + tablet.screenChanged.connect(onScreenChanged); + + function cleanup() { + tablet.removeButton(button); + tablet.screenChanged.disconnect(onScreenChanged); + } + Script.scriptEnding.connect(cleanup); + +}()); diff --git a/scripts/system/controllers/handControllerGrab.js b/scripts/system/controllers/handControllerGrab.js index c8b78b4d08..f614020880 100644 --- a/scripts/system/controllers/handControllerGrab.js +++ b/scripts/system/controllers/handControllerGrab.js @@ -3446,7 +3446,7 @@ function MyController(hand) { if (intersectInfo) { var pointerEvent = { type: "Press", - id: HARDWARE_MOUSE_ID, + id: this.hand + 1, pos2D: projectOntoOverlayXYPlane(this.grabbedOverlay, intersectInfo.point), pos3D: intersectInfo.point, normal: intersectInfo.normal, @@ -3495,7 +3495,7 @@ function MyController(hand) { if (this.deadspotExpired) { pointerEvent = { type: "Release", - id: HARDWARE_MOUSE_ID, + id: this.hand + 1, pos2D: pos2D, pos3D: pos3D, normal: intersectInfo.normal, @@ -3539,7 +3539,7 @@ function MyController(hand) { var pointerEvent = { type: "Move", - id: HARDWARE_MOUSE_ID, + id: this.hand + 1, pos2D: pos2D, pos3D: pos3D, normal: intersectInfo.normal,