From 155ae07b7083cc7960f0f4425eb11849254d78ad Mon Sep 17 00:00:00 2001 From: James McDonnell Date: Tue, 21 Nov 2017 14:18:21 -0500 Subject: Add support for showWithoutActivating windows Includes pop-up windows which are implicitly showWithoutActivating windows. The QNX platform code was allowing screen to activate these windows when they were shown. Add code to activate showWithoutActivating windows when they are first touched or clicked on. From there, screen handles activation as it does for any other window. Change-Id: If443676e497a97724e16037b34d3db1d7c335790 Reviewed-by: Dan Cape Reviewed-by: Janne Koskinen Reviewed-by: Rafael Roquetto --- .../platforms/qnx/qqnxscreeneventhandler.cpp | 5 ++ src/plugins/platforms/qnx/qqnxwindow.cpp | 88 ++++++++++++++++++++-- src/plugins/platforms/qnx/qqnxwindow.h | 4 + 3 files changed, 90 insertions(+), 7 deletions(-) diff --git a/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp b/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp index e4843cb438..f29e11489b 100644 --- a/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp +++ b/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp @@ -381,6 +381,8 @@ void QQnxScreenEventHandler::handlePointerEvent(screen_event_t event) if (m_lastGlobalMousePoint != globalPoint || m_lastLocalMousePoint != localPoint || m_lastButtonState != buttons) { + if (m_lastButtonState != 0 && buttons == 0) + (static_cast(w->handle()))->handleActivationEvent(); QWindowSystemInterface::handleMouseEvent(w, localPoint, globalPoint, buttons); qScreenEventDebug() << "Qt mouse, w=" << w << ", (" << localPoint.x() << "," << localPoint.y() << "), b=" << static_cast(buttons); } @@ -457,6 +459,9 @@ void QQnxScreenEventHandler::handleTouchEvent(screen_event_t event, int qnxType) m_lastMouseWindow = qnxWindow; if (w) { + if (qnxType == SCREEN_EVENT_MTOUCH_RELEASE) + (static_cast(w->handle()))->handleActivationEvent(); + // get size of screen which contains window QPlatformScreen *platformScreen = QPlatformScreen::platformScreenForWindow(w); QSizeF screenSize = platformScreen->geometry().size(); diff --git a/src/plugins/platforms/qnx/qqnxwindow.cpp b/src/plugins/platforms/qnx/qqnxwindow.cpp index 5d9eaaa3ea..7c98b29348 100644 --- a/src/plugins/platforms/qnx/qqnxwindow.cpp +++ b/src/plugins/platforms/qnx/qqnxwindow.cpp @@ -166,7 +166,8 @@ QQnxWindow::QQnxWindow(QWindow *window, screen_context_t context, bool needRootW m_visible(false), m_exposed(true), m_windowState(Qt::WindowNoState), - m_mmRendererWindow(0) + m_mmRendererWindow(0), + m_firstActivateHandled(false) { qWindowDebug() << "window =" << window << ", size =" << window->size(); @@ -351,6 +352,14 @@ void QQnxWindow::setVisible(bool visible) if (visible) { applyWindowState(); } else { + if (showWithoutActivating() && focusable() && m_firstActivateHandled) { + m_firstActivateHandled = false; + int val = SCREEN_SENSITIVITY_NO_FOCUS; + Q_SCREEN_CHECKERROR( + screen_set_window_property_iv(m_window, SCREEN_PROPERTY_SENSITIVITY, &val), + "Failed to set window sensitivity"); + } + // Flush the context, otherwise it won't disappear immediately screen_flush_context(m_screenContext, 0); } @@ -628,13 +637,56 @@ void QQnxWindow::requestActivateWindow() void QQnxWindow::setFocus(screen_window_t newFocusWindow) { + screen_window_t temporaryFocusWindow = nullptr; + screen_group_t screenGroup = 0; - screen_get_window_property_pv(nativeHandle(), SCREEN_PROPERTY_GROUP, - reinterpret_cast(&screenGroup)); - if (screenGroup) { - screen_set_group_property_pv(screenGroup, SCREEN_PROPERTY_FOCUS, - reinterpret_cast(&newFocusWindow)); + Q_SCREEN_CHECKERROR(screen_get_window_property_pv(nativeHandle(), SCREEN_PROPERTY_GROUP, + reinterpret_cast(&screenGroup)), + "Failed to retrieve window group"); + + if (showWithoutActivating() && focusable() && !m_firstActivateHandled) { + m_firstActivateHandled = true; + int val = SCREEN_SENSITIVITY_TEST; + Q_SCREEN_CHECKERROR( + screen_set_window_property_iv(m_window, SCREEN_PROPERTY_SENSITIVITY, &val), + "Failed to set window sensitivity"); + +#if _SCREEN_VERSION < _SCREEN_MAKE_VERSION(1, 0, 0) + // For older versions of screen, the window may still have group + // focus even though it was marked NO_FOCUS when it was hidden. + // In that situation, focus has to be given to another window + // so that this window can take focus back from it. + screen_window_t oldFocusWindow = nullptr; + Q_SCREEN_CHECKERROR( + screen_get_group_property_pv(screenGroup, SCREEN_PROPERTY_FOCUS, + reinterpret_cast(&oldFocusWindow)), + "Failed to retrieve group focus"); + if (newFocusWindow == oldFocusWindow) { + char groupName[256]; + memset(groupName, 0, sizeof(groupName)); + Q_SCREEN_CHECKERROR(screen_get_group_property_cv(screenGroup, SCREEN_PROPERTY_NAME, + sizeof(groupName) - 1, groupName), + "Failed to retrieve group name"); + + Q_SCREEN_CHECKERROR(screen_create_window_type(&temporaryFocusWindow, + m_screenContext, SCREEN_CHILD_WINDOW), + "Failed to create temporary focus window"); + Q_SCREEN_CHECKERROR(screen_join_window_group(temporaryFocusWindow, groupName), + "Temporary focus window failed to join window group"); + Q_SCREEN_CHECKERROR( + screen_set_group_property_pv(screenGroup, SCREEN_PROPERTY_FOCUS, + reinterpret_cast(&temporaryFocusWindow)), + "Temporary focus window failed to take focus"); + screen_flush_context(m_screenContext, 0); + } +#endif } + + Q_SCREEN_CHECKERROR(screen_set_group_property_pv(screenGroup, SCREEN_PROPERTY_FOCUS, + reinterpret_cast(&newFocusWindow)), + "Failed to set group focus"); + + screen_destroy_window(temporaryFocusWindow); } void QQnxWindow::setWindowState(Qt::WindowStates state) @@ -721,7 +773,11 @@ void QQnxWindow::initWindow() screen_set_window_property_iv(m_window, SCREEN_PROPERTY_SWAP_INTERVAL, &val), "Failed to set swap interval"); - if (window()->flags() & Qt::WindowDoesNotAcceptFocus) { + if (showWithoutActivating() || !focusable()) { + // NO_FOCUS is temporary for showWithoutActivating (and pop-up) windows. + // Using NO_FOCUS ensures that screen doesn't activate the window because + // it was just created. Sensitivity will be changed to TEST when the + // window is clicked or touched. val = SCREEN_SENSITIVITY_NO_FOCUS; Q_SCREEN_CHECKERROR( screen_set_window_property_iv(m_window, SCREEN_PROPERTY_SENSITIVITY, &val), @@ -835,4 +891,22 @@ bool QQnxWindow::shouldMakeFullScreen() const && (QQnxIntegration::instance()->options() & QQnxIntegration::FullScreenApplication)); } + +void QQnxWindow::handleActivationEvent() +{ + if (showWithoutActivating() && focusable() && !m_firstActivateHandled) + requestActivateWindow(); +} + +bool QQnxWindow::showWithoutActivating() const +{ + return (window()->flags() & Qt::Popup) == Qt::Popup + || window()->property("_q_showWithoutActivating").toBool(); +} + +bool QQnxWindow::focusable() const +{ + return (window()->flags() & Qt::WindowDoesNotAcceptFocus) != Qt::WindowDoesNotAcceptFocus; +} + QT_END_NAMESPACE diff --git a/src/plugins/platforms/qnx/qqnxwindow.h b/src/plugins/platforms/qnx/qqnxwindow.h index 2895a547b1..20c38cb4b7 100644 --- a/src/plugins/platforms/qnx/qqnxwindow.h +++ b/src/plugins/platforms/qnx/qqnxwindow.h @@ -113,6 +113,7 @@ public: bool shouldMakeFullScreen() const; void windowPosted(); + void handleActivationEvent(); protected: virtual int pixelFormat() const = 0; @@ -131,6 +132,8 @@ private: void updateZorder(screen_window_t window, int &zOrder); void applyWindowState(); void setFocus(screen_window_t newFocusWindow); + bool showWithoutActivating() const; + bool focusable() const; screen_window_t m_window; QSize m_bufferSize; @@ -152,6 +155,7 @@ private: QByteArray m_parentGroupName; bool m_isTopLevel; + bool m_firstActivateHandled; }; QT_END_NAMESPACE -- cgit v1.2.3