Merge pull request #9990 from hyperlogic/bug-fix/sliders

Added inputMode property to Web3DOverlay
This commit is contained in:
Seth Alves 2017-03-28 10:07:37 -07:00 committed by GitHub
commit 9e675d4c93
7 changed files with 309 additions and 31 deletions

View file

@ -237,10 +237,7 @@ void Web3DOverlay::render(RenderArgs* args) {
std::weak_ptr<Web3DOverlay> weakSelf = std::dynamic_pointer_cast<Web3DOverlay>(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);
}
};
@ -254,22 +251,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<QTouchEvent::TouchPoint> 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);
@ -346,6 +330,14 @@ void Web3DOverlay::setProxyWindow(QWindow* proxyWindow) {
}
void Web3DOverlay::handlePointerEvent(const PointerEvent& event) {
if (_inputMode == Touch) {
handlePointerEventAsTouch(event);
} else {
handlePointerEventAsMouse(event);
}
}
void Web3DOverlay::handlePointerEventAsTouch(const PointerEvent& event) {
if (!_webSurface) {
return;
}
@ -353,16 +345,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;
}
@ -401,6 +393,47 @@ void Web3DOverlay::handlePointerEvent(const PointerEvent& event) {
QCoreApplication::postEvent(_webSurface->getWindow(), touchEvent);
}
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);
@ -443,6 +476,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) {
@ -464,6 +507,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);
}

View file

@ -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<OffscreenQmlSurface> _webSurface;
QMetaObject::Connection _connection;
gpu::TexturePointer _texture;

View file

@ -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;
}

View file

@ -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

View file

@ -0,0 +1,157 @@
<!--
// quick_start_template.html
//
// Created by Faye Li on 3 Feb 2017
// Copyright 2017 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
-->
<html>
<head>
<title>Slider Test</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://fonts.googleapis.com/css?family=Raleway:300,400,600,700"" rel="stylesheet">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-slider/9.7.2/css/bootstrap-slider.min.css">
<!-- <link rel="stylesheet" href="http://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.css" /> -->
<style>
body {
margin: 0;
width: 100%;
font-family: 'Raleway', sans-serif;
color: white;
background: linear-gradient(#2b2b2b, #0f212e);
}
.top-bar {
height: 90px;
background: linear-gradient(#2b2b2b, #1e1e1e);
font-weight: bold;
padding-left: 30px;
padding-right: 30px;
display: flex;
align-items: center;
position: fixed;
width: 480px;
top: 0;
z-index: 1;
}
.content {
margin-top: 90px;
padding: 30px;
}
input[type=button] {
font-family: 'Raleway';
font-weight: bold;
font-size: 13px;
text-transform: uppercase;
vertical-align: top;
height: 28px;
min-width: 120px;
padding: 0px 18px;
margin-right: 6px;
border-radius: 5px;
border: none;
color: #fff;
background-color: #000;
background: linear-gradient(#343434 20%, #000 100%);
cursor: pointer;
}
input[type=button].red {
color: #fff;
background-color: #94132e;
background: linear-gradient(#d42043 20%, #94132e 100%);
}
input[type=button].blue {
color: #fff;
background-color: #1080b8;
background: linear-gradient(#00b4ef 20%, #1080b8 100%);
}
input[type=button].white {
color: #121212;
background-color: #afafaf;
background: linear-gradient(#fff 20%, #afafaf 100%);
}
input[type=button]:enabled:hover {
background: linear-gradient(#000, #000);
border: none;
}
input[type=button].red:enabled:hover {
background: linear-gradient(#d42043, #d42043);
border: none;
}
input[type=button].blue:enabled:hover {
background: linear-gradient(#00b4ef, #00b4ef);
border: none;
}
input[type=button].white:enabled:hover {
background: linear-gradient(#fff, #fff);
border: none;
}
input[type=button]:active {
background: linear-gradient(#343434, #343434);
}
input[type=button].red:active {
background: linear-gradient(#94132e, #94132e);
}
input[type=button].blue:active {
background: linear-gradient(#1080b8, #1080b8);
}
input[type=button].white:active {
background: linear-gradient(#afafaf, #afafaf);
}
input[type=button]:disabled {
color: #252525;
background: linear-gradient(#575757 20%, #252525 100%);
}
input[type=button][pressed=pressed] {
color: #00b4ef;
}
</style>
</head>
<body>
<div class="top-bar">
<h4>Slider Test</h4>
</div>
<div class="content">
<p>Native Input Range Slider</p>
<p>
<input type="range" name="native-slider" id="native-slider" value="60" min="0" max="100">
</p>
<p>Bootstrap Slider</p>
<p>
<input
id="bootstrap-slider"
type="text"
data-provide="slider"
data-slider-min="0"
data-slider-max="100"
data-slider-step="1"
data-slider-value="60"
data-slider-tooltip="hide"
>
</p>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-slider/9.7.2/bootstrap-slider.min.js"></script>
<script>
function main() {
console.log("ready");
}
$(document).ready(main);
</script>
</body>
</html>

View file

@ -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);
}());

View file

@ -3467,7 +3467,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,
@ -3516,7 +3516,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,
@ -3560,7 +3560,7 @@ function MyController(hand) {
var pointerEvent = {
type: "Move",
id: HARDWARE_MOUSE_ID,
id: this.hand + 1,
pos2D: pos2D,
pos3D: pos3D,
normal: intersectInfo.normal,