std::shared_ptr<View> WindowView_Impl::get_capture_view(PointerEvent &e, std::shared_ptr<View> &view_above_cursor) { if (e.type() == PointerEventType::press || e.type() == PointerEventType::double_click) { capture_down_counter++; if (capture_down_counter == 1) { captured_view = view_above_cursor; if (captured_view) window.capture_mouse(true); } } std::shared_ptr<View> view = captured_view; if (e.type() == PointerEventType::release) { if (capture_down_counter > 0) { capture_down_counter--; if (capture_down_counter == 0) { if (captured_view) release_capture(); } } } return view; }
PointerEvent* PointerEventFactoryTest::createAndCheckTouchCancel( WebPointerProperties::PointerType pointerType, int rawId, int uniqueId, bool isPrimary) { PointerEvent* pointerEvent = m_pointerEventFactory.createPointerCancelEvent( uniqueId, pointerType); EXPECT_EQ(uniqueId, pointerEvent->pointerId()); EXPECT_EQ(isPrimary, pointerEvent->isPrimary()); return pointerEvent; }
PointerEvent* PointerEventFactoryTest::createAndCheckMouseEvent( WebPointerProperties::PointerType pointerType, int rawId, int uniqueId, bool isPrimary, PlatformEvent::Modifiers modifiers) { PointerEvent* pointerEvent = m_pointerEventFactory.create( EventTypeNames::mousedown, PlatformMouseEventBuilder(pointerType, rawId, modifiers), nullptr, nullptr); EXPECT_EQ(uniqueId, pointerEvent->pointerId()); EXPECT_EQ(isPrimary, pointerEvent->isPrimary()); return pointerEvent; }
void PointerEventFactoryTest::createAndCheckPointerTransitionEvent( PointerEvent* pointerEvent, const AtomicString& type) { PointerEvent* clonePointerEvent = m_pointerEventFactory. createPointerTransitionEvent(pointerEvent, type, nullptr); EXPECT_EQ(clonePointerEvent->pointerType(), pointerEvent->pointerType()); EXPECT_EQ(clonePointerEvent->pointerId(), pointerEvent->pointerId()); EXPECT_EQ(clonePointerEvent->isPrimary(), pointerEvent->isPrimary()); EXPECT_EQ(clonePointerEvent->type(), type); }
PointerEvent* PointerEventFactoryTest::createAndCheckTouchEvent( WebPointerProperties::PointerType pointerType, int rawId, int uniqueId, bool isPrimary, PlatformTouchPoint::TouchState state) { PointerEvent* pointerEvent = m_pointerEventFactory.create( EventTypeNames::pointerdown, PointerEventFactoryTest::PlatformTouchPointBuilder(pointerType, rawId, state), PlatformEvent::NoModifiers, FloatSize(), FloatPoint()); EXPECT_EQ(uniqueId, pointerEvent->pointerId()); EXPECT_EQ(isPrimary, pointerEvent->isPrimary()); return pointerEvent; }
void WindowView_Impl::window_pointer_event(PointerEvent &e) { std::shared_ptr<View> view_above_cursor = window_view->find_view_at(e.pos(window_view)); auto view = get_capture_view(e, view_above_cursor); if (!view) view = view_above_cursor; dispatch_hot_event(view, e); if (e.type() == PointerEventType::enter || e.type() == PointerEventType::leave) // Ignore window enter/leave events return; if (view) view->dispatch_event(&e); else window_view->dispatch_event(&e); }
void ScriptEditorInput::onPointerPressed(const PointerEvent& ev) { MonoObject* screenPos = ScriptVector2I::box(ev.screenPos); MonoObject* delta = ScriptVector2I::box(ev.delta); MonoUtil::invokeThunk(OnPointerPressedThunk, screenPos, delta, ev.button, ev.shift, ev.control, ev.alt, ev.mouseWheelScrollAmount, ev.isUsed()); }
void ListBoxViewImpl::on_pointer_release(PointerEvent &e) { if (e.phase() != EventUIPhase::bubbling || e.button() != PointerButton::left) return; int index = get_selection_index(e); // Only allow click when mouse released over component if (index == selected_item) { if (func_selection_changed) func_selection_changed(); } else { listbox->set_selected_item(last_selected_item); } }
void ListBoxViewImpl::on_pointer_press(PointerEvent &e) { if (e.button() != PointerButton::left) return; last_selected_item = selected_item; int index = get_selection_index(e); listbox->set_selected_item(index); }
void SliderViewImpl::on_pointer_thumb_press(PointerEvent &e) { if (_state_disabled) return; _state_pressed = true; update_state(); mouse_down_mode = mouse_down_thumb_drag; thumb_move_start_position = _position; mouse_drag_start_pos = e.pos(track.get()); }
void ScriptInput::onPointerDoubleClick(const PointerEvent& ev) { if (PlayInEditorManager::instance().getState() != PlayInEditorState::Playing) return; MonoObject* screenPos = ScriptVector2I::box(ev.screenPos); MonoObject* delta = ScriptVector2I::box(ev.delta); MonoUtil::invokeThunk(OnPointerDoubleClickThunk, screenPos, delta, ev.button, ev.shift, ev.control, ev.alt, ev.mouseWheelScrollAmount, ev.isUsed()); }
int ListBoxViewImpl::get_selection_index(PointerEvent &e) { int index = 0; for (auto &view : listbox->content_view()->children()) { if (view->geometry().border_box().contains(e.pos(listbox->content_view()))) return index; index++; } return -1; }
void ButtonViewImpl::on_pointer_release(PointerEvent &e) { _state_pressed = false; if (_state_disabled) return; update_state(); if (_func_clicked) { if (button->geometry().border_box().contains(e.local_pos())) // Only allow click when mouse released over component _func_clicked(); } }
void CheckBoxView_Impl::on_pointer_release(PointerEvent &e) { _state_pressed = false; if (_state_disabled) return; if (checkbox->geometry().border_box().contains(e.local_pos())) // Only allow click when mouse released over component { _checked_state = !_checked_state; if (_func_state_changed) _func_state_changed(); } update_state(); }
void WindowView_Impl::dispatch_hot_event(std::shared_ptr<View> &view, PointerEvent &e) { if (view != hot_view) { if (hot_view) { PointerEvent e_exit(PointerEventType::leave, PointerButton::none, e.pos(window_view->root_view()), e.alt_down(), e.shift_down(), e.ctrl_down(), e.cmd_down()); hot_view->dispatch_event(&e_exit, true); } hot_view = view; if (hot_view) { PointerEvent e_enter(PointerEventType::enter, PointerButton::none, e.pos(window_view->root_view()), e.alt_down(), e.shift_down(), e.ctrl_down(), e.cmd_down()); hot_view->dispatch_event(&e_enter, true); } } if (hot_view) hot_view->update_cursor(window); }
void SliderViewImpl::on_pointer_move(PointerEvent &e) { if (_state_disabled) return; if (mouse_down_mode != mouse_down_thumb_drag) { return; } Pointf mouse_pos(e.pos(track.get())); Rectf track_geometry(track->geometry().content_box()); int last_position = _position; if (mouse_pos.x < -100 || mouse_pos.x > track_geometry.get_width() + 100 || mouse_pos.y < -100 || mouse_pos.y > track_geometry.get_height() + 100) { _position = thumb_move_start_position; } else { if (slider->horizontal()) { int delta = (mouse_pos.x - mouse_drag_start_pos.x); _position = thumb_move_start_position + (delta * (_max_position - _min_position)) / (track->geometry().content_box().get_width()); } else { int delta = (mouse_pos.y - mouse_drag_start_pos.y); _position = thumb_move_start_position + (delta * (_max_position - _min_position)) / (track->geometry().content_box().get_height()); } } if (_position > _max_position) _position = _max_position; if (_position < _min_position) _position = _min_position; if (_lock_to_ticks) { int remainder = (_position - _min_position) % _tick_count; _position = _position - remainder; } if (last_position != _position) { if (_func_value_changed) _func_value_changed(); slider->set_needs_layout(); } }
void SliderViewImpl::on_pointer_track_press(PointerEvent &e) { if (_state_disabled) return; if (e.target() == thumb) // Thumb control handled elsewhere return; float mouse_pos; Rectf thumb_geometry(thumb->geometry().content_box()); float thumb_position; if (slider->horizontal()) { mouse_pos = e.pos(track.get()).x; thumb_position = thumb_geometry.left + thumb_geometry.get_width() / 2.0f; timer_target_position = _min_position + mouse_pos * ((_max_position - _min_position)) / (track->geometry().content_box().get_width()); } else { mouse_pos = e.pos(track.get()).y; thumb_position = thumb_geometry.top + thumb_geometry.get_height() / 2.0f; timer_target_position = _min_position + mouse_pos * ((_max_position - _min_position)) / (track->geometry().content_box().get_height()); } if (mouse_pos < thumb_position) { mouse_down_mode = mouse_down_track_decr; timer_step_size = -_page_step; } else { mouse_down_mode = mouse_down_track_incr; timer_step_size = _page_step; } scroll_timer_expired(); }
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; } Qt::MouseButton button = Qt::NoButton; if (event.getButton() == PointerEvent::PrimaryButton) { button = Qt::LeftButton; } QEvent::Type type; switch (event.getType()) { case PointerEvent::Press: type = QEvent::MouseButtonPress; break; case PointerEvent::Release: type = QEvent::MouseButtonRelease; break; case PointerEvent::Move: type = QEvent::MouseMove; break; default: return; } QMouseEvent mouseEvent(type, windowPoint, windowPoint, windowPoint, button, buttons, Qt::NoModifier); QCoreApplication::sendEvent(_webSurface->getWindow(), &mouseEvent); }
/**jsdoc * <p>A KeyboardModifiers value is used to specify which modifier keys on the keyboard are pressed. The value is the sum * (bitwise OR) of the relevant combination of values from the following table:</p> * <table> * <thead> * <tr><th>Key</th><th>Hexadecimal value</th><th>Decimal value</th><th>Description</th></tr> * </thead> * <tbody> * <tr><td>Shift</td><td><code>0x02000000</code></td><td><code>33554432</code></td> * <td>A Shift key on the keyboard is pressed.</td></tr> * <tr><td>Control</td><td><code>0x04000000</code></td><td><code>67108864</code></td> * <td>A Control key on the keyboard is pressed.</td></tr> * <tr><td>Alt</td><td><code>0x08000000</code></td><td><code>134217728</code></td> * <td>An Alt key on the keyboard is pressed.</td></tr> * <tr><td>Meta</td><td><code>0x10000000</code></td><td><code>268435456</code></td> * <td>A Meta or Windows key on the keyboard is pressed.</td></tr> * <tr><td>Keypad</td><td><code>0x20000000</code></td><td><code>536870912</code></td> * <td>A keypad button is pressed.</td></tr> * <tr><td>Group</td><td><code>0x40000000</code></td><td><code>1073741824</code></td> * <td>X11 operating system only: An AltGr / Mode_switch key on the keyboard is pressed.</td></tr> * </tbody> * </table> * @typedef {number} KeyboardModifiers */ QScriptValue PointerEvent::toScriptValue(QScriptEngine* engine, const PointerEvent& event) { QScriptValue obj = engine->newObject(); switch (event._type) { case Press: obj.setProperty("type", "Press"); break; case DoublePress: obj.setProperty("type", "DoublePress"); break; case Release: obj.setProperty("type", "Release"); break; default: case Move: obj.setProperty("type", "Move"); break; }; obj.setProperty("id", event._id); QScriptValue pos2D = engine->newObject(); pos2D.setProperty("x", event._pos2D.x); pos2D.setProperty("y", event._pos2D.y); obj.setProperty("pos2D", pos2D); QScriptValue pos3D = engine->newObject(); pos3D.setProperty("x", event._pos3D.x); pos3D.setProperty("y", event._pos3D.y); pos3D.setProperty("z", event._pos3D.z); obj.setProperty("pos3D", pos3D); QScriptValue normal = engine->newObject(); normal.setProperty("x", event._normal.x); normal.setProperty("y", event._normal.y); normal.setProperty("z", event._normal.z); obj.setProperty("normal", normal); QScriptValue direction = engine->newObject(); direction.setProperty("x", event._direction.x); direction.setProperty("y", event._direction.y); direction.setProperty("z", event._direction.z); obj.setProperty("direction", direction); bool isPrimaryButton = false; bool isSecondaryButton = false; bool isTertiaryButton = false; switch (event._button) { case NoButtons: obj.setProperty("button", "None"); break; case PrimaryButton: obj.setProperty("button", "Primary"); isPrimaryButton = true; break; case SecondaryButton: obj.setProperty("button", "Secondary"); isSecondaryButton = true; break; case TertiaryButton: obj.setProperty("button", "Tertiary"); isTertiaryButton = true; break; } if (isPrimaryButton) { obj.setProperty("isPrimaryButton", isPrimaryButton); obj.setProperty("isLeftButton", isPrimaryButton); } if (isSecondaryButton) { obj.setProperty("isSecondaryButton", isSecondaryButton); obj.setProperty("isRightButton", isSecondaryButton); } if (isTertiaryButton) { obj.setProperty("isTertiaryButton", isTertiaryButton); obj.setProperty("isMiddleButton", isTertiaryButton); } obj.setProperty("isPrimaryHeld", areFlagsSet(event._buttons, PrimaryButton)); obj.setProperty("isSecondaryHeld", areFlagsSet(event._buttons, SecondaryButton)); obj.setProperty("isTertiaryHeld", areFlagsSet(event._buttons, TertiaryButton)); obj.setProperty("keyboardModifiers", QScriptValue(event.getKeyboardModifiers())); return obj; }
void RenderableWebEntityItem::handlePointerEvent(const PointerEvent& event) { // Ignore mouse interaction if we're locked if (getLocked() || !_webSurface) { return; } glm::vec2 windowPos = event.getPos2D() * (METERS_TO_INCHES * _dpi); QPointF windowPoint(windowPos.x, windowPos.y); if (event.getType() == PointerEvent::Move) { // Forward a mouse move event to webSurface QMouseEvent* mouseEvent = new QMouseEvent(QEvent::MouseMove, windowPoint, windowPoint, windowPoint, Qt::NoButton, Qt::NoButton, Qt::NoModifier); QCoreApplication::postEvent(_webSurface->getWindow(), mouseEvent); } { // Forward a touch update event to webSurface if (event.getType() == PointerEvent::Press) { this->_pressed = true; } else if (event.getType() == PointerEvent::Release) { this->_pressed = false; } QEvent::Type type; Qt::TouchPointState touchPointState; switch (event.getType()) { case PointerEvent::Press: type = QEvent::TouchBegin; touchPointState = Qt::TouchPointPressed; break; case PointerEvent::Release: type = QEvent::TouchEnd; touchPointState = Qt::TouchPointReleased; break; case PointerEvent::Move: default: type = QEvent::TouchUpdate; touchPointState = Qt::TouchPointMoved; break; } QTouchEvent::TouchPoint point; point.setId(event.getID()); point.setState(touchPointState); point.setPos(windowPoint); point.setScreenPos(windowPoint); QList<QTouchEvent::TouchPoint> touchPoints; touchPoints.push_back(point); QTouchEvent* touchEvent = new QTouchEvent(type); touchEvent->setWindow(nullptr); touchEvent->setDevice(nullptr); touchEvent->setTarget(nullptr); touchEvent->setTouchPoints(touchPoints); touchEvent->setTouchPointStates(touchPointState); _lastTouchEvent = *touchEvent; QCoreApplication::postEvent(_webSurface->getWindow(), touchEvent); } }
void Pointer::generatePointerEvents(unsigned int pointerID, const PickResultPointer& pickResult) { // TODO: avatars/HUD? auto pointerManager = DependencyManager::get<PointerManager>(); // NOTE: After this loop: _prevButtons = buttons that were removed // If switching to disabled or should stop triggering, release all buttons Buttons buttons; Buttons newButtons; Buttons sameButtons; if (_enabled && shouldTrigger(pickResult)) { buttons = getPressedButtons(pickResult); for (const std::string& button : buttons) { if (_prevButtons.find(button) == _prevButtons.end()) { newButtons.insert(button); } else { sameButtons.insert(button); _prevButtons.erase(button); } } } // Hover events bool doHover = shouldHover(pickResult); Pointer::PickedObject hoveredObject = getHoveredObject(pickResult); PointerEvent hoveredEvent = buildPointerEvent(hoveredObject, pickResult); hoveredEvent.setType(PointerEvent::Move); hoveredEvent.setID(pointerID); bool moveOnHoverLeave = (!_enabled && _prevEnabled) || (!doHover && _prevDoHover); hoveredEvent.setMoveOnHoverLeave(moveOnHoverLeave); // if shouldHover && !_prevDoHover, only send hoverBegin if (_enabled && _hover && doHover && !_prevDoHover) { if (hoveredObject.type == ENTITY) { emit pointerManager->hoverBeginEntity(hoveredObject.objectID, hoveredEvent); } else if (hoveredObject.type == LOCAL_ENTITY) { emit pointerManager->hoverBeginOverlay(hoveredObject.objectID, hoveredEvent); } else if (hoveredObject.type == HUD) { emit pointerManager->hoverBeginHUD(hoveredEvent); } } else if (_enabled && _hover && doHover) { if (hoveredObject.type == LOCAL_ENTITY) { if (_prevHoveredObject.type == LOCAL_ENTITY) { if (hoveredObject.objectID == _prevHoveredObject.objectID) { emit pointerManager->hoverContinueOverlay(hoveredObject.objectID, hoveredEvent); } else { PointerEvent prevHoveredEvent = buildPointerEvent(_prevHoveredObject, pickResult); prevHoveredEvent.setID(pointerID); prevHoveredEvent.setMoveOnHoverLeave(moveOnHoverLeave); emit pointerManager->hoverEndOverlay(_prevHoveredObject.objectID, prevHoveredEvent); emit pointerManager->hoverBeginOverlay(hoveredObject.objectID, hoveredEvent); } } else { emit pointerManager->hoverBeginOverlay(hoveredObject.objectID, hoveredEvent); if (_prevHoveredObject.type == ENTITY) { emit pointerManager->hoverEndEntity(_prevHoveredObject.objectID, hoveredEvent); } else if (_prevHoveredObject.type == HUD) { emit pointerManager->hoverEndHUD(hoveredEvent); } } } // TODO: this is basically repeated code. is there a way to clean it up? if (hoveredObject.type == ENTITY) { if (_prevHoveredObject.type == ENTITY) { if (hoveredObject.objectID == _prevHoveredObject.objectID) { emit pointerManager->hoverContinueEntity(hoveredObject.objectID, hoveredEvent); } else { PointerEvent prevHoveredEvent = buildPointerEvent(_prevHoveredObject, pickResult); prevHoveredEvent.setID(pointerID); prevHoveredEvent.setMoveOnHoverLeave(moveOnHoverLeave); emit pointerManager->hoverEndEntity(_prevHoveredObject.objectID, prevHoveredEvent); emit pointerManager->hoverBeginEntity(hoveredObject.objectID, hoveredEvent); } } else { emit pointerManager->hoverBeginEntity(hoveredObject.objectID, hoveredEvent); if (_prevHoveredObject.type == LOCAL_ENTITY) { emit pointerManager->hoverEndOverlay(_prevHoveredObject.objectID, hoveredEvent); } else if (_prevHoveredObject.type == HUD) { emit pointerManager->hoverEndHUD(hoveredEvent); } } } if (hoveredObject.type == HUD) { if (_prevHoveredObject.type == HUD) { // There's only one HUD emit pointerManager->hoverContinueHUD(hoveredEvent); } else { emit pointerManager->hoverBeginHUD(hoveredEvent); if (_prevHoveredObject.type == ENTITY) { emit pointerManager->hoverEndEntity(_prevHoveredObject.objectID, hoveredEvent); } else if (_prevHoveredObject.type == LOCAL_ENTITY) { emit pointerManager->hoverEndOverlay(_prevHoveredObject.objectID, hoveredEvent); } } } if (hoveredObject.type == NONE) { if (_prevHoveredObject.type == ENTITY) { emit pointerManager->hoverEndEntity(_prevHoveredObject.objectID, hoveredEvent); } else if (_prevHoveredObject.type == LOCAL_ENTITY) { emit pointerManager->hoverEndOverlay(_prevHoveredObject.objectID, hoveredEvent); } else if (_prevHoveredObject.type == HUD) { emit pointerManager->hoverEndHUD(hoveredEvent); } } } // Trigger begin const std::string SHOULD_FOCUS_BUTTON = "Focus"; for (const std::string& button : newButtons) { hoveredEvent.setType(PointerEvent::Press); hoveredEvent.setButton(chooseButton(button)); hoveredEvent.setShouldFocus(button == SHOULD_FOCUS_BUTTON); if (hoveredObject.type == ENTITY) { emit pointerManager->triggerBeginEntity(hoveredObject.objectID, hoveredEvent); } else if (hoveredObject.type == LOCAL_ENTITY) { emit pointerManager->triggerBeginOverlay(hoveredObject.objectID, hoveredEvent); } else if (hoveredObject.type == HUD) { emit pointerManager->triggerBeginHUD(hoveredEvent); } _triggeredObjects[button] = hoveredObject; } // Trigger continue for (const std::string& button : sameButtons) { PointerEvent triggeredEvent = buildPointerEvent(_triggeredObjects[button], pickResult, button, false); triggeredEvent.setID(pointerID); triggeredEvent.setType(PointerEvent::Move); triggeredEvent.setButton(chooseButton(button)); if (_triggeredObjects[button].type == ENTITY) { emit pointerManager->triggerContinueEntity(_triggeredObjects[button].objectID, triggeredEvent); } else if (_triggeredObjects[button].type == LOCAL_ENTITY) { emit pointerManager->triggerContinueOverlay(_triggeredObjects[button].objectID, triggeredEvent); } else if (_triggeredObjects[button].type == HUD) { emit pointerManager->triggerContinueHUD(triggeredEvent); } } // Trigger end for (const std::string& button : _prevButtons) { PointerEvent triggeredEvent = buildPointerEvent(_triggeredObjects[button], pickResult, button, false); triggeredEvent.setID(pointerID); triggeredEvent.setType(PointerEvent::Release); triggeredEvent.setButton(chooseButton(button)); if (_triggeredObjects[button].type == ENTITY) { emit pointerManager->triggerEndEntity(_triggeredObjects[button].objectID, triggeredEvent); } else if (_triggeredObjects[button].type == LOCAL_ENTITY) { emit pointerManager->triggerEndOverlay(_triggeredObjects[button].objectID, triggeredEvent); } else if (_triggeredObjects[button].type == HUD) { emit pointerManager->triggerEndHUD(triggeredEvent); } _triggeredObjects.erase(button); } // if we disable the pointer or disable hovering, send hoverEnd events after triggerEnd if (_hover && ((!_enabled && _prevEnabled) || (!doHover && _prevDoHover))) { if (_prevHoveredObject.type == ENTITY) { emit pointerManager->hoverEndEntity(_prevHoveredObject.objectID, hoveredEvent); } else if (_prevHoveredObject.type == LOCAL_ENTITY) { emit pointerManager->hoverEndOverlay(_prevHoveredObject.objectID, hoveredEvent); } else if (_prevHoveredObject.type == HUD) { emit pointerManager->hoverEndHUD(hoveredEvent); } } _prevHoveredObject = hoveredObject; _prevButtons = buttons; _prevEnabled = _enabled; _prevDoHover = doHover; }
void Web3DOverlay::handlePointerEventAsTouch(const PointerEvent& event) { if (!_webSurface) { return; } //do not send secondary button events to tablet if (event.getButton() == PointerEvent::SecondaryButton || //do not block composed events event.getButtons() == PointerEvent::SecondaryButton) { return; } QPointF windowPoint; { glm::vec2 windowPos = event.getPos2D() * (METERS_TO_INCHES * _dpi); windowPoint = QPointF(windowPos.x, windowPos.y); } Qt::TouchPointState state = Qt::TouchPointStationary; if (event.getType() == PointerEvent::Press && event.getButton() == PointerEvent::PrimaryButton) { state = Qt::TouchPointPressed; } else if (event.getType() == PointerEvent::Release) { state = Qt::TouchPointReleased; } else if (_activeTouchPoints.count(event.getID()) && windowPoint != _activeTouchPoints[event.getID()].pos()) { state = Qt::TouchPointMoved; } QEvent::Type touchType = QEvent::TouchUpdate; if (_activeTouchPoints.empty()) { // If the first active touch point is being created, send a begin touchType = QEvent::TouchBegin; } if (state == Qt::TouchPointReleased && _activeTouchPoints.size() == 1 && _activeTouchPoints.count(event.getID())) { // If the last active touch point is being released, send an end touchType = QEvent::TouchEnd; } { QTouchEvent::TouchPoint point; point.setId(event.getID()); point.setState(state); point.setPos(windowPoint); point.setScreenPos(windowPoint); _activeTouchPoints[event.getID()] = point; } QTouchEvent touchEvent(touchType, &_touchDevice, event.getKeyboardModifiers()); { QList<QTouchEvent::TouchPoint> touchPoints; Qt::TouchPointStates touchPointStates; for (const auto& entry : _activeTouchPoints) { touchPointStates |= entry.second.state(); touchPoints.push_back(entry.second); } touchEvent.setWindow(_webSurface->getWindow()); touchEvent.setTarget(_webSurface->getRootItem()); touchEvent.setTouchPoints(touchPoints); touchEvent.setTouchPointStates(touchPointStates); } // Send mouse events to the Web surface so that HTML dialog elements work with mouse press and hover. // FIXME: Scroll bar dragging is a bit unstable in the tablet (content can jump up and down at times). // This may be improved in Qt 5.8. Release notes: "Cleaned up touch and mouse event delivery". // // In Qt 5.9 mouse events must be sent before touch events to make sure some QtQuick components will // receive mouse events Qt::MouseButton button = Qt::NoButton; Qt::MouseButtons buttons = Qt::NoButton; if (event.getButton() == PointerEvent::PrimaryButton) { button = Qt::LeftButton; } if (event.getButtons() & PointerEvent::PrimaryButton) { buttons |= Qt::LeftButton; } #if QT_VERSION >= QT_VERSION_CHECK(5, 9, 0) if (event.getType() == PointerEvent::Move) { QMouseEvent mouseEvent(QEvent::MouseMove, windowPoint, windowPoint, windowPoint, button, buttons, Qt::NoModifier); QCoreApplication::sendEvent(_webSurface->getWindow(), &mouseEvent); } #endif if (touchType == QEvent::TouchBegin) { _touchBeginAccepted = QCoreApplication::sendEvent(_webSurface->getWindow(), &touchEvent); } else if (_touchBeginAccepted) { QCoreApplication::sendEvent(_webSurface->getWindow(), &touchEvent); } // If this was a release event, remove the point from the active touch points if (state == Qt::TouchPointReleased) { _activeTouchPoints.erase(event.getID()); } #if QT_VERSION < QT_VERSION_CHECK(5, 9, 0) if (event.getType() == PointerEvent::Move) { QMouseEvent mouseEvent(QEvent::MouseMove, windowPoint, windowPoint, windowPoint, button, buttons, Qt::NoModifier); QCoreApplication::sendEvent(_webSurface->getWindow(), &mouseEvent); } #endif }