diff options
Diffstat (limited to 'src/plugins/platforms')
22 files changed, 333 insertions, 245 deletions
diff --git a/src/plugins/platforms/cocoa/qcocoacursor.mm b/src/plugins/platforms/cocoa/qcocoacursor.mm index c021128e4c..8c98dc69f7 100644 --- a/src/plugins/platforms/cocoa/qcocoacursor.mm +++ b/src/plugins/platforms/cocoa/qcocoacursor.mm @@ -314,6 +314,7 @@ NSCursor *QCocoaCursor::createCursorFromPixmap(const QPixmap pixmap, const QPoin if (pixmap.devicePixelRatio() > 1.0) { QSize layoutSize = pixmap.size() / pixmap.devicePixelRatio(); QPixmap scaledPixmap = pixmap.scaled(layoutSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); + scaledPixmap.setDevicePixelRatio(1.0); nsimage = static_cast<NSImage *>(qt_mac_create_nsimage(scaledPixmap)); CGImageRef cgImage = qt_mac_toCGImage(pixmap.toImage()); NSBitmapImageRep *imageRep = [[NSBitmapImageRep alloc] initWithCGImage:cgImage]; diff --git a/src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm b/src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm index 9a96895d07..815882ab06 100644 --- a/src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm +++ b/src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm @@ -73,8 +73,6 @@ static QFont qfontForCocoaFont(NSFont *cocoaFont, const QFont &resolveFont) return newFont; } -@class QT_MANGLE_NAMESPACE(QNSFontPanelDelegate); - @interface QT_MANGLE_NAMESPACE(QNSFontPanelDelegate) : NSObject<NSWindowDelegate, QNSPanelDelegate> { @public @@ -110,7 +108,8 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSFontPanelDelegate); [mFontPanel setRestorable:NO]; [mFontPanel setDelegate:self]; - [[NSFontManager sharedFontManager] setDelegate:self]; + + [NSFontManager sharedFontManager].target = self; // Action is changeFont: [mFontPanel retain]; return self; @@ -120,7 +119,7 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSFontPanelDelegate); { [mStolenContentView release]; [mFontPanel setDelegate:nil]; - [[NSFontManager sharedFontManager] setDelegate:nil]; + [NSFontManager sharedFontManager].target = nil; [[NSNotificationCenter defaultCenter] removeObserver:self]; [super dealloc]; diff --git a/src/plugins/platforms/cocoa/qcocoahelpers.mm b/src/plugins/platforms/cocoa/qcocoahelpers.mm index b729c7f4c0..e5954f277c 100644 --- a/src/plugins/platforms/cocoa/qcocoahelpers.mm +++ b/src/plugins/platforms/cocoa/qcocoahelpers.mm @@ -265,6 +265,16 @@ QRectF qt_mac_flip(const QRectF &rect, const QRectF &reference) // ------------------------------------------------------------------------- +/*! + \fn Qt::MouseButton cocoaButton2QtButton(NSInteger buttonNum) + + Returns the Qt::Button that corresponds to an NSEvent.buttonNumber. + + \note AppKit will use buttonNumber 0 to indicate both "left button" + and "no button". Only NSEvents that describes mouse press/release + events (e.g NSEventTypeOtherMouseDown) will contain a valid + button number. +*/ Qt::MouseButton cocoaButton2QtButton(NSInteger buttonNum) { if (buttonNum >= 0 && buttonNum <= 31) diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index 54254455e4..1e311ed388 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -404,8 +404,10 @@ void QCocoaWindow::setVisible(bool visible) removeMonitor(); monitor = [NSEvent addGlobalMonitorForEventsMatchingMask:NSLeftMouseDownMask|NSRightMouseDownMask|NSOtherMouseDownMask|NSMouseMovedMask handler:^(NSEvent *e) { QPointF localPoint = QCocoaScreen::mapFromNative([NSEvent mouseLocation]); + const auto button = e.type == NSEventTypeMouseMoved ? Qt::NoButton : cocoaButton2QtButton([e buttonNumber]); + const auto eventType = e.type == NSEventTypeMouseMoved ? QEvent::MouseMove : QEvent::MouseButtonPress; QWindowSystemInterface::handleMouseEvent(window(), window()->mapFromGlobal(localPoint.toPoint()), localPoint, - cocoaButton2QtButton([e buttonNumber])); + Qt::MouseButtons(uint(NSEvent.pressedMouseButtons & 0xFFFF)), button, eventType); }]; } } @@ -1334,7 +1336,7 @@ void QCocoaWindow::recreateWindowIfNeeded() void QCocoaWindow::requestUpdate() { qCDebug(lcQpaCocoaDrawing) << "QCocoaWindow::requestUpdate" << window(); - [qnsview_cast(m_view) requestUpdate]; + QPlatformWindow::requestUpdate(); } void QCocoaWindow::requestActivateWindow() diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index a88cd5feda..c88ffc76d7 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -358,7 +358,7 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet") m_platformWindow->handleExposeEvent(dirtyRegion); } - if (windowPrivate->updateRequestPending) { + if (m_updateRequested && windowPrivate->updateRequestPending) { // A call to QWindow::requestUpdate was issued during event delivery above, // but AppKit will reset the needsDisplay state of the view after completing // the current display cycle, so we need to defer the request to redisplay. diff --git a/src/plugins/platforms/cocoa/qprintengine_mac.mm b/src/plugins/platforms/cocoa/qprintengine_mac.mm index b3d48c1ec3..eade407500 100644 --- a/src/plugins/platforms/cocoa/qprintengine_mac.mm +++ b/src/plugins/platforms/cocoa/qprintengine_mac.mm @@ -574,6 +574,11 @@ void QMacPrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &va d->setPageSize(QPageSize(QPageSize::id(value.toInt()))); break; case PPK_PrinterName: { + QVariant pageSize = QVariant::fromValue(d->m_pageLayout.pageSize()); + const bool isFullPage = d->m_pageLayout.mode() == QPageLayout::FullPageMode; + QVariant orientation = QVariant::fromValue(d->m_pageLayout.orientation()); + QVariant margins = QVariant::fromValue(QPair<QMarginsF, QPageLayout::Unit>(d->m_pageLayout.margins(), + d->m_pageLayout.units())); QString id = value.toString(); if (id.isEmpty()) id = QCocoaPrinterSupport().defaultPrintDeviceId(); @@ -583,7 +588,14 @@ void QMacPrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &va PMPrinter printer = d->m_printDevice->macPrinter(); PMRetain(printer); PMSessionSetCurrentPMPrinter(d->session(), printer); - // TODO Do we need to check if the page size, etc, are valid on new printer? + // Ensure the settings are up to date and valid + if (d->m_printDevice->supportedPageSize(pageSize.value<QPageSize>()).isValid()) + setProperty(PPK_QPageSize, pageSize); + else + setProperty(PPK_CustomPaperSize, pageSize.value<QPageSize>().size(QPageSize::Point)); + setProperty(PPK_FullPage, QVariant(isFullPage)); + setProperty(PPK_Orientation, orientation); + setProperty(PPK_QPageMargins, margins); break; } case PPK_CustomPaperSize: diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_rcar/qeglfsrcarintegration.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_rcar/qeglfsrcarintegration.cpp index 98cf1d3bfb..212ebde05a 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_rcar/qeglfsrcarintegration.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_rcar/qeglfsrcarintegration.cpp @@ -52,12 +52,28 @@ QT_BEGIN_NAMESPACE void QEglFSRcarIntegration::platformInit() { + bool ok; + QEglFSDeviceIntegration::platformInit(); PVRGrfxServerInit(); mScreenSize = q_screenSizeFromFb(0); mNativeDisplay = (NativeDisplayType)EGL_DEFAULT_DISPLAY; + + mNativeDisplayID = qEnvironmentVariableIntValue("QT_QPA_WM_DISP_ID", &ok); + if (!ok) + mNativeDisplayID = RCAR_DEFAULT_DISPLAY; + + r_wm_Error_t wm_err = R_WM_DevInit(mNativeDisplayID); + if (wm_err != R_WM_ERR_OK) + qFatal("Failed to init WM Dev: %d, error: %d", mNativeDisplayID, wm_err); + wm_err = R_WM_ScreenBgColorSet(mNativeDisplayID, 0x20, 0x20, 0x20); // Grey + if (wm_err != R_WM_ERR_OK) + qFatal("Failed to set screen background: %d", wm_err); + wm_err = R_WM_ScreenEnable(mNativeDisplayID); + if (wm_err != R_WM_ERR_OK) + qFatal("Failed to enable screen: %d", wm_err); } QSize QEglFSRcarIntegration::screenSize() const @@ -104,14 +120,6 @@ EGLNativeWindowType QEglFSRcarIntegration::createNativeWindow(QPlatformWindow *w { bool ok; - mNativeDisplayID = qEnvironmentVariableIntValue("QT_QPA_WM_DISP_ID", &ok); - if (!ok) - mNativeDisplayID = RCAR_DEFAULT_DISPLAY; - - r_wm_Error_t wm_err = R_WM_DevInit(mNativeDisplayID); - if (wm_err != R_WM_ERR_OK) - qFatal("Failed to init WM Dev: %d, error: %d", mNativeDisplayID, wm_err); - mNativeWindow = (EGLNativeWindowTypeREL*)malloc(sizeof(EGLNativeWindowTypeREL)); memset(mNativeWindow, 0, sizeof(EGLNativeWindowTypeREL)); @@ -134,7 +142,7 @@ EGLNativeWindowType QEglFSRcarIntegration::createNativeWindow(QPlatformWindow *w mNativeWindow->Surface.Type = R_WM_SURFACE_FB; mNativeWindow->Surface.BufMode = R_WM_WINBUF_ALLOC_INTERNAL; - wm_err = R_WM_WindowCreate(mNativeDisplayID, mNativeWindow); + r_wm_Error_t wm_err = R_WM_WindowCreate(mNativeDisplayID, mNativeWindow); if (wm_err != R_WM_ERR_OK) qFatal("Failed to create window layer: %d", wm_err); wm_err = R_WM_DevEventRegister(mNativeDisplayID, R_WM_EVENT_VBLANK, 0); diff --git a/src/plugins/platforms/qnx/qqnxkeytranslator.h b/src/plugins/platforms/qnx/qqnxkeytranslator.h index 043e38fec9..9400b88dbb 100644 --- a/src/plugins/platforms/qnx/qqnxkeytranslator.h +++ b/src/plugins/platforms/qnx/qqnxkeytranslator.h @@ -48,179 +48,68 @@ QT_BEGIN_NAMESPACE -Qt::Key keyTranslator( int key ) +int qtKeyForPrivateUseQnxKey( int key ) { switch (key) { - case KEYCODE_PAUSE: - return Qt::Key_Pause; - - case KEYCODE_SCROLL_LOCK: - return Qt::Key_ScrollLock; - - case KEYCODE_PRINT: - return Qt::Key_Print; - - case KEYCODE_SYSREQ: - return Qt::Key_SysReq; - + case KEYCODE_PAUSE: return Qt::Key_Pause; + case KEYCODE_SCROLL_LOCK: return Qt::Key_ScrollLock; + case KEYCODE_PRINT: return Qt::Key_Print; + case KEYCODE_SYSREQ: return Qt::Key_SysReq; // case KEYCODE_BREAK: - - case KEYCODE_ESCAPE: - return Qt::Key_Escape; - - case KEYCODE_BACKSPACE: - return Qt::Key_Backspace; - - case KEYCODE_TAB: - return Qt::Key_Tab; - - case KEYCODE_BACK_TAB: - return Qt::Key_Backtab; - - case KEYCODE_RETURN: - return Qt::Key_Return; - - case KEYCODE_CAPS_LOCK: - return Qt::Key_CapsLock; - - case KEYCODE_LEFT_SHIFT: - case KEYCODE_RIGHT_SHIFT: - return Qt::Key_Shift; - - case KEYCODE_LEFT_CTRL: - case KEYCODE_RIGHT_CTRL: - return Qt::Key_Control; - - case KEYCODE_LEFT_ALT: - case KEYCODE_RIGHT_ALT: - return Qt::Key_Alt; - - case KEYCODE_MENU: - return Qt::Key_Menu; - - case KEYCODE_LEFT_HYPER: - return Qt::Key_Hyper_L; - - case KEYCODE_RIGHT_HYPER: - return Qt::Key_Hyper_R; - - case KEYCODE_INSERT: - return Qt::Key_Insert; - - case KEYCODE_HOME: - return Qt::Key_Home; - - case KEYCODE_PG_UP: - return Qt::Key_PageUp; - - case KEYCODE_DELETE: - return Qt::Key_Delete; - - case KEYCODE_END: - return Qt::Key_End; - - case KEYCODE_PG_DOWN: - return Qt::Key_PageDown; - - case KEYCODE_LEFT: - return Qt::Key_Left; - - case KEYCODE_RIGHT: - return Qt::Key_Right; - - case KEYCODE_UP: - return Qt::Key_Up; - - case KEYCODE_DOWN: - return Qt::Key_Down; - - case KEYCODE_NUM_LOCK: - return Qt::Key_NumLock; - - case KEYCODE_KP_PLUS: - return Qt::Key_Plus; - - case KEYCODE_KP_MINUS: - return Qt::Key_Minus; - - case KEYCODE_KP_MULTIPLY: - return Qt::Key_Asterisk; - - case KEYCODE_KP_DIVIDE: - return Qt::Key_Slash; - - case KEYCODE_KP_ENTER: - return Qt::Key_Enter; - - case KEYCODE_KP_HOME: - return Qt::Key_Home; - - case KEYCODE_KP_UP: - return Qt::Key_Up; - - case KEYCODE_KP_PG_UP: - return Qt::Key_PageUp; - - case KEYCODE_KP_LEFT: - return Qt::Key_Left; - - // Is this right? - case KEYCODE_KP_FIVE: - return Qt::Key_5; - - case KEYCODE_KP_RIGHT: - return Qt::Key_Right; - - case KEYCODE_KP_END: - return Qt::Key_End; - - case KEYCODE_KP_DOWN: - return Qt::Key_Down; - - case KEYCODE_KP_PG_DOWN: - return Qt::Key_PageDown; - - case KEYCODE_KP_INSERT: - return Qt::Key_Insert; - - case KEYCODE_KP_DELETE: - return Qt::Key_Delete; - - case KEYCODE_F1: - return Qt::Key_F1; - - case KEYCODE_F2: - return Qt::Key_F2; - - case KEYCODE_F3: - return Qt::Key_F3; - - case KEYCODE_F4: - return Qt::Key_F4; - - case KEYCODE_F5: - return Qt::Key_F5; - - case KEYCODE_F6: - return Qt::Key_F6; - - case KEYCODE_F7: - return Qt::Key_F7; - - case KEYCODE_F8: - return Qt::Key_F8; - - case KEYCODE_F9: - return Qt::Key_F9; - - case KEYCODE_F10: - return Qt::Key_F10; - - case KEYCODE_F11: - return Qt::Key_F11; - - case KEYCODE_F12: - return Qt::Key_F12; + case KEYCODE_ESCAPE: return Qt::Key_Escape; + case KEYCODE_BACKSPACE: return Qt::Key_Backspace; + case KEYCODE_TAB: return Qt::Key_Tab; + case KEYCODE_BACK_TAB: return Qt::Key_Backtab; + case KEYCODE_RETURN: return Qt::Key_Return; + case KEYCODE_CAPS_LOCK: return Qt::Key_CapsLock; + case KEYCODE_LEFT_SHIFT: return Qt::Key_Shift; + case KEYCODE_RIGHT_SHIFT: return Qt::Key_Shift; + case KEYCODE_LEFT_CTRL: return Qt::Key_Control; + case KEYCODE_RIGHT_CTRL: return Qt::Key_Control; + case KEYCODE_LEFT_ALT: return Qt::Key_Alt; + case KEYCODE_RIGHT_ALT: return Qt::Key_Alt; + case KEYCODE_MENU: return Qt::Key_Menu; + case KEYCODE_LEFT_HYPER: return Qt::Key_Hyper_L; + case KEYCODE_RIGHT_HYPER: return Qt::Key_Hyper_R; + case KEYCODE_INSERT: return Qt::Key_Insert; + case KEYCODE_HOME: return Qt::Key_Home; + case KEYCODE_PG_UP: return Qt::Key_PageUp; + case KEYCODE_DELETE: return Qt::Key_Delete; + case KEYCODE_END: return Qt::Key_End; + case KEYCODE_PG_DOWN: return Qt::Key_PageDown; + case KEYCODE_LEFT: return Qt::Key_Left; + case KEYCODE_RIGHT: return Qt::Key_Right; + case KEYCODE_UP: return Qt::Key_Up; + case KEYCODE_DOWN: return Qt::Key_Down; + case KEYCODE_NUM_LOCK: return Qt::Key_NumLock; + case KEYCODE_KP_PLUS: return Qt::Key_Plus; + case KEYCODE_KP_MINUS: return Qt::Key_Minus; + case KEYCODE_KP_MULTIPLY: return Qt::Key_Asterisk; + case KEYCODE_KP_DIVIDE: return Qt::Key_Slash; + case KEYCODE_KP_ENTER: return Qt::Key_Enter; + case KEYCODE_KP_HOME: return Qt::Key_Home; + case KEYCODE_KP_UP: return Qt::Key_Up; + case KEYCODE_KP_PG_UP: return Qt::Key_PageUp; + case KEYCODE_KP_LEFT: return Qt::Key_Left; + case KEYCODE_KP_FIVE: return Qt::Key_5; + case KEYCODE_KP_RIGHT: return Qt::Key_Right; + case KEYCODE_KP_END: return Qt::Key_End; + case KEYCODE_KP_DOWN: return Qt::Key_Down; + case KEYCODE_KP_PG_DOWN: return Qt::Key_PageDown; + case KEYCODE_KP_INSERT: return Qt::Key_Insert; + case KEYCODE_KP_DELETE: return Qt::Key_Delete; + case KEYCODE_F1: return Qt::Key_F1; + case KEYCODE_F2: return Qt::Key_F2; + case KEYCODE_F3: return Qt::Key_F3; + case KEYCODE_F4: return Qt::Key_F4; + case KEYCODE_F5: return Qt::Key_F5; + case KEYCODE_F6: return Qt::Key_F6; + case KEYCODE_F7: return Qt::Key_F7; + case KEYCODE_F8: return Qt::Key_F8; + case KEYCODE_F9: return Qt::Key_F9; + case KEYCODE_F10: return Qt::Key_F10; + case KEYCODE_F11: return Qt::Key_F11; + case KEYCODE_F12: return Qt::Key_F12; // See keycodes.h for more, but these are all the basics. And printables are already included. @@ -231,7 +120,21 @@ Qt::Key keyTranslator( int key ) break; } - return Qt::Key_Escape; + return Qt::Key_unknown; +} + +QString keyStringForPrivateUseQnxKey( int key ) +{ + switch (key) { + case KEYCODE_ESCAPE: return QStringLiteral("\x1B"); + case KEYCODE_BACKSPACE: return QStringLiteral("\b"); + case KEYCODE_TAB: return QStringLiteral("\t"); + case KEYCODE_RETURN: return QStringLiteral("\r"); + case KEYCODE_DELETE: return QStringLiteral("\x7F"); + case KEYCODE_KP_ENTER: return QStringLiteral("\r"); + } + + return QString(); } bool isKeypadKey( int key ) diff --git a/src/plugins/platforms/qnx/qqnxnativeinterface.cpp b/src/plugins/platforms/qnx/qqnxnativeinterface.cpp index 3eebb9c742..3bd6a86b59 100644 --- a/src/plugins/platforms/qnx/qqnxnativeinterface.cpp +++ b/src/plugins/platforms/qnx/qqnxnativeinterface.cpp @@ -91,6 +91,9 @@ void *QQnxNativeInterface::nativeResourceForScreen(const QByteArray &resource, Q void *QQnxNativeInterface::nativeResourceForIntegration(const QByteArray &resource) { + if (resource == "screenContext") + return m_integration->screenContext(); + return 0; } diff --git a/src/plugins/platforms/qnx/qqnxrasterwindow.cpp b/src/plugins/platforms/qnx/qqnxrasterwindow.cpp index dc844189d1..0014ef8c6e 100644 --- a/src/plugins/platforms/qnx/qqnxrasterwindow.cpp +++ b/src/plugins/platforms/qnx/qqnxrasterwindow.cpp @@ -158,7 +158,7 @@ QQnxBuffer &QQnxRasterWindow::renderBuffer() "Failed to clear window buffer"); } - Q_SCREEN_CHECKERROR(screen_flush_blits(platformScreen->nativeContext(), 0), + Q_SCREEN_CHECKERROR(screen_flush_blits(platformScreen->nativeContext(), SCREEN_WAIT_IDLE), "Failed to flush blits"); // Use the first available render buffer diff --git a/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp b/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp index 5d230e2145..ff1133aaa7 100644 --- a/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp +++ b/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp @@ -58,6 +58,37 @@ #define qScreenEventDebug QT_NO_QDEBUG_MACRO #endif +static int qtKey(int virtualKey, QChar::Category category) +{ + if (Q_UNLIKELY(category == QChar::Other_NotAssigned)) + return virtualKey; + else if (category == QChar::Other_PrivateUse) + return qtKeyForPrivateUseQnxKey(virtualKey); + else + return QChar::toUpper(virtualKey); +} + +static QString keyString(int sym, QChar::Category category) +{ + if (Q_UNLIKELY(category == QChar::Other_NotAssigned)) { + return QString(); + } else if (category == QChar::Other_PrivateUse) { + return keyStringForPrivateUseQnxKey(sym); + } else { + uint ucs4_sym = sym; + return QString::fromUcs4(&ucs4_sym, 1); + } +} + +static QString capKeyString(int cap, int modifiers, int key) +{ + if (cap >= 0x20 && cap <= 0x0ff) { + if (modifiers & KEYMOD_CTRL) + return QChar((int)(key & 0x3f)); + } + return QString(); +} + QT_BEGIN_NAMESPACE QQnxScreenEventHandler::QQnxScreenEventHandler(QQnxIntegration *integration) @@ -154,6 +185,13 @@ void QQnxScreenEventHandler::injectKeyboardEvent(int flags, int sym, int modifie { Q_UNUSED(scan); + if (!(flags & KEY_CAP_VALID)) + return; + + // Correct erroneous information. + if ((flags & KEY_SYM_VALID) && sym == static_cast<int>(0xFFFFFFFF)) + flags &= ~(KEY_SYM_VALID); + Qt::KeyboardModifiers qtMod = Qt::NoModifier; if (modifiers & KEYMOD_SHIFT) qtMod |= Qt::ShiftModifier; @@ -161,37 +199,20 @@ void QQnxScreenEventHandler::injectKeyboardEvent(int flags, int sym, int modifie qtMod |= Qt::ControlModifier; if (modifiers & KEYMOD_ALT) qtMod |= Qt::AltModifier; + if (isKeypadKey(cap)) + qtMod |= Qt::KeypadModifier; - // determine event type QEvent::Type type = (flags & KEY_DOWN) ? QEvent::KeyPress : QEvent::KeyRelease; - // Check if the key cap is valid - if (flags & KEY_CAP_VALID) { - Qt::Key key; - QString keyStr; + int virtualKey = (flags & KEY_SYM_VALID) ? sym : cap; + QChar::Category category = QChar::category(virtualKey); + int key = qtKey(virtualKey, category); + QString keyStr = (flags & KEY_SYM_VALID) ? keyString(sym, category) : + capKeyString(cap, modifiers, key); - if (cap >= 0x20 && cap <= 0x0ff) { - key = Qt::Key(std::toupper(cap)); // Qt expects the CAP to be upper case. - - if ( qtMod & Qt::ControlModifier ) { - keyStr = QChar((int)(key & 0x3f)); - } else { - if (flags & KEY_SYM_VALID) - keyStr = QChar(sym); - } - } else if ((cap > 0x0ff && cap < UNICODE_PRIVATE_USE_AREA_FIRST) || cap > UNICODE_PRIVATE_USE_AREA_LAST) { - key = (Qt::Key)cap; - keyStr = QChar(sym); - } else { - if (isKeypadKey(cap)) - qtMod |= Qt::KeypadModifier; // Is this right? - key = keyTranslator(cap); - } - - QWindowSystemInterface::handleExtendedKeyEvent(QGuiApplication::focusWindow(), type, key, qtMod, - scan, sym, modifiers, keyStr); - qScreenEventDebug() << "Qt key t=" << type << ", k=" << key << ", s=" << keyStr; - } + QWindowSystemInterface::handleExtendedKeyEvent(QGuiApplication::focusWindow(), type, key, qtMod, + scan, virtualKey, modifiers, keyStr); + qScreenEventDebug() << "Qt key t=" << type << ", k=" << key << ", s=" << keyStr; } void QQnxScreenEventHandler::setScreenEventThread(QQnxScreenEventThread *eventThread) @@ -591,6 +612,10 @@ void QQnxScreenEventHandler::handlePropertyEvent(screen_event_t event) case SCREEN_PROPERTY_FOCUS: handleKeyboardFocusPropertyEvent(window); break; + case SCREEN_PROPERTY_SIZE: + case SCREEN_PROPERTY_POSITION: + handleGeometryPropertyEvent(window); + break; default: // event ignored qScreenEventDebug() << "Ignore property event for property: " << property; @@ -617,6 +642,28 @@ void QQnxScreenEventHandler::handleKeyboardFocusPropertyEvent(screen_window_t wi m_focusLostTimer = startTimer(50); } +void QQnxScreenEventHandler::handleGeometryPropertyEvent(screen_window_t window) +{ + int pos[2]; + if (screen_get_window_property_iv(window, SCREEN_PROPERTY_POSITION, pos) != 0) { + qFatal("QQnx: failed to query window property, errno=%d", errno); + } + + int size[2]; + if (screen_get_window_property_iv(window, SCREEN_PROPERTY_SIZE, size) != 0) { + qFatal("QQnx: failed to query window property, errno=%d", errno); + } + + QRect rect(pos[0], pos[1], size[0], size[1]); + QWindow *qtWindow = QQnxIntegration::window(window); + if (qtWindow) { + qtWindow->setGeometry(rect); + QWindowSystemInterface::handleGeometryChange(qtWindow, rect); + } + + qScreenEventDebug() << qtWindow << "moved to" << rect; +} + void QQnxScreenEventHandler::timerEvent(QTimerEvent *event) { if (event->timerId() == m_focusLostTimer) { diff --git a/src/plugins/platforms/qnx/qqnxscreeneventhandler.h b/src/plugins/platforms/qnx/qqnxscreeneventhandler.h index d872f9b9aa..40697b7a09 100644 --- a/src/plugins/platforms/qnx/qqnxscreeneventhandler.h +++ b/src/plugins/platforms/qnx/qqnxscreeneventhandler.h @@ -85,6 +85,7 @@ private: void handleDisplayEvent(screen_event_t event); void handlePropertyEvent(screen_event_t event); void handleKeyboardFocusPropertyEvent(screen_window_t window); + void handleGeometryPropertyEvent(screen_window_t window); private: enum { diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp index 072012064f..98a4b261fd 100644 --- a/src/plugins/platforms/windows/qwindowscontext.cpp +++ b/src/plugins/platforms/windows/qwindowscontext.cpp @@ -246,14 +246,12 @@ struct QWindowsContextPrivate { QScopedPointer<QWindowsTabletSupport> m_tabletSupport; #endif const HRESULT m_oleInitializeResult; - const QByteArray m_eventType; QWindow *m_lastActiveWindow = nullptr; bool m_asyncExpose = false; }; QWindowsContextPrivate::QWindowsContextPrivate() : m_oleInitializeResult(OleInitialize(NULL)) - , m_eventType(QByteArrayLiteral("windows_generic_MSG")) { QWindowsContext::user32dll.init(); QWindowsContext::shcoredll.init(); @@ -866,6 +864,33 @@ static bool shouldHaveNonClientDpiScaling(const QWindow *window) ; } +static inline bool isInputMessage(UINT m) +{ + switch (m) { + case WM_IME_STARTCOMPOSITION: + case WM_IME_ENDCOMPOSITION: + case WM_IME_COMPOSITION: + case WM_TOUCH: + case WM_MOUSEHOVER: + case WM_MOUSELEAVE: + case WM_NCHITTEST: + case WM_NCMOUSEHOVER: + case WM_NCMOUSELEAVE: + case WM_SIZING: + case WM_MOVING: + case WM_SYSCOMMAND: + case WM_COMMAND: + case WM_DWMNCRENDERINGCHANGED: + case WM_PAINT: + return true; + default: + break; + } + return (m >= WM_MOUSEFIRST && m <= WM_MOUSELAST) + || (m >= WM_NCMOUSEMOVE && m <= WM_NCXBUTTONDBLCLK) + || (m >= WM_KEYFIRST && m <= WM_KEYLAST); +} + /*! \brief Main windows procedure registered for windows. @@ -901,21 +926,14 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message, QWindowsWindow *platformWindow = findPlatformWindow(hwnd); *platformWindowPtr = platformWindow; - // Run the native event filters. - long filterResult = 0; - QAbstractEventDispatcher* dispatcher = QAbstractEventDispatcher::instance(); - if (dispatcher && dispatcher->filterNativeEvent(d->m_eventType, &msg, &filterResult)) { - *result = LRESULT(filterResult); + // Run the native event filters. QTBUG-67095: Exclude input messages which are sent + // by QEventDispatcherWin32::processEvents() + if (!isInputMessage(msg.message) && filterNativeEvent(&msg, result)) + return true; + + if (platformWindow && filterNativeEvent(platformWindow->window(), &msg, result)) return true; - } - if (platformWindow) { - filterResult = 0; - if (QWindowSystemInterface::handleNativeEvent(platformWindow->window(), d->m_eventType, &msg, &filterResult)) { - *result = LRESULT(filterResult); - return true; - } - } if (et & QtWindows::InputMethodEventFlag) { QWindowsInputContext *windowsInputContext = ::windowsInputContext(); // Disable IME assuming this is a special implementation hooking into keyboard input. @@ -1393,4 +1411,30 @@ extern "C" LRESULT QT_WIN_CALLBACK qWindowsWndProc(HWND hwnd, UINT message, WPAR return result; } + +static inline QByteArray nativeEventType() { return QByteArrayLiteral("windows_generic_MSG"); } + +// Send to QAbstractEventDispatcher +bool QWindowsContext::filterNativeEvent(MSG *msg, LRESULT *result) +{ + QAbstractEventDispatcher *dispatcher = QAbstractEventDispatcher::instance(); + long filterResult = 0; + if (dispatcher && dispatcher->filterNativeEvent(nativeEventType(), msg, &filterResult)) { + *result = LRESULT(filterResult); + return true; + } + return false; +} + +// Send to QWindowSystemInterface +bool QWindowsContext::filterNativeEvent(QWindow *window, MSG *msg, LRESULT *result) +{ + long filterResult = 0; + if (QWindowSystemInterface::handleNativeEvent(window, nativeEventType(), &msg, &filterResult)) { + *result = LRESULT(filterResult); + return true; + } + return false; +} + QT_END_NAMESPACE diff --git a/src/plugins/platforms/windows/qwindowscontext.h b/src/plugins/platforms/windows/qwindowscontext.h index f2ec307be2..0a7f20ca83 100644 --- a/src/plugins/platforms/windows/qwindowscontext.h +++ b/src/plugins/platforms/windows/qwindowscontext.h @@ -212,6 +212,9 @@ public: QTouchDevice *touchDevice() const; + static bool filterNativeEvent(MSG *msg, LRESULT *result); + static bool filterNativeEvent(QWindow *window, MSG *msg, LRESULT *result); + private: void handleFocusEvent(QtWindows::WindowsEventType et, QWindowsWindow *w); #ifndef QT_NO_CONTEXTMENU diff --git a/src/plugins/platforms/windows/qwindowsinputcontext.cpp b/src/plugins/platforms/windows/qwindowsinputcontext.cpp index b9dd2c557e..2dbca6047c 100644 --- a/src/plugins/platforms/windows/qwindowsinputcontext.cpp +++ b/src/plugins/platforms/windows/qwindowsinputcontext.cpp @@ -530,6 +530,14 @@ bool QWindowsInputContext::endComposition(HWND hwnd) if (m_compositionContext.focusObject.isNull()) return false; + // QTBUG-58300: Ignore WM_IME_ENDCOMPOSITION when CTRL is pressed to prevent + // for example the text being cleared when pressing CTRL+A + if (m_locale.language() == QLocale::Korean + && QGuiApplication::queryKeyboardModifiers().testFlag(Qt::ControlModifier)) { + reset(); + return true; + } + m_endCompositionRecursionGuard = true; imeNotifyCancelComposition(m_compositionContext.hwnd); diff --git a/src/plugins/platforms/windows/qwindowskeymapper.cpp b/src/plugins/platforms/windows/qwindowskeymapper.cpp index af62936a18..950d8ecd36 100644 --- a/src/plugins/platforms/windows/qwindowskeymapper.cpp +++ b/src/plugins/platforms/windows/qwindowskeymapper.cpp @@ -102,6 +102,7 @@ QWindowsKeyMapper::QWindowsKeyMapper() QGuiApplication *app = static_cast<QGuiApplication *>(QGuiApplication::instance()); QObject::connect(app, &QGuiApplication::applicationStateChanged, app, clearKeyRecorderOnApplicationInActive); + changeKeyboard(); } QWindowsKeyMapper::~QWindowsKeyMapper() @@ -317,9 +318,9 @@ static const uint KeyTbl[] = { // Keyboard mapping table Qt::Key_9, // 105 0x69 VK_NUMPAD9 | Numeric keypad 9 key Qt::Key_Asterisk, // 106 0x6A VK_MULTIPLY | Multiply key Qt::Key_Plus, // 107 0x6B VK_ADD | Add key - Qt::Key_Comma, // 108 0x6C VK_SEPARATOR | Separator key + Qt::Key_unknown, // 108 0x6C VK_SEPARATOR | Separator key (locale-dependent) Qt::Key_Minus, // 109 0x6D VK_SUBTRACT | Subtract key - Qt::Key_Period, // 110 0x6E VK_DECIMAL | Decimal key + Qt::Key_unknown, // 110 0x6E VK_DECIMAL | Decimal key (locale-dependent) Qt::Key_Slash, // 111 0x6F VK_DIVIDE | Divide key Qt::Key_F1, // 112 0x70 VK_F1 | F1 key Qt::Key_F2, // 113 0x71 VK_F2 | F2 key @@ -810,7 +811,7 @@ bool QWindowsKeyMapper::translateKeyEvent(QWindow *widget, HWND hwnd, // Reset layout map when system keyboard layout is changed if (msg.message == WM_INPUTLANGCHANGE) { - deleteLayouts(); + changeKeyboard(); return true; } @@ -830,7 +831,7 @@ bool QWindowsKeyMapper::translateKeyEvent(QWindow *widget, HWND hwnd, if (PeekMessage(&peekedMsg, hwnd, 0, 0, PM_NOREMOVE) && peekedMsg.message == WM_DEADCHAR) return true; - return translateKeyEventInternal(widget, msg, false); + return translateKeyEventInternal(widget, msg, false, result); } bool QWindowsKeyMapper::translateMultimediaKeyEventInternal(QWindow *window, const MSG &msg) @@ -854,15 +855,19 @@ bool QWindowsKeyMapper::translateMultimediaKeyEventInternal(QWindow *window, con sendExtendedPressRelease(receiver, qtKey, Qt::KeyboardModifier(state), 0, 0, 0); // QTBUG-43343: Make sure to return false if Qt does not handle the key, otherwise, // the keys are not passed to the active media player. +# if QT_CONFIG(shortcut) const QKeySequence sequence(Qt::Modifier(state) + qtKey); return QGuiApplicationPrivate::instance()->shortcutMap.hasShortcutForKeySequence(sequence); +# else + return false; +# endif #else Q_UNREACHABLE(); return false; #endif } -bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, const MSG &msg, bool /* grab */) +bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, const MSG &msg, bool /* grab */, LRESULT *lResult) { const UINT msgType = msg.message; @@ -1056,6 +1061,10 @@ bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, const MSG &ms QChar uch; if (PeekMessage(&wm_char, 0, charType, charType, PM_REMOVE)) { + if (QWindowsContext::filterNativeEvent(&wm_char, lResult)) + return true; + if (receiver && QWindowsContext::filterNativeEvent(receiver, &wm_char, lResult)) + return true; // Found a ?_CHAR uch = QChar(ushort(wm_char.wParam)); if (uch.isHighSurrogate()) { @@ -1264,8 +1273,19 @@ QList<int> QWindowsKeyMapper::possibleKeys(const QKeyEvent *e) const for (size_t i = 1; i < NumMods; ++i) { Qt::KeyboardModifiers neededMods = ModsTbl[i]; quint32 key = kbItem.qtKey[i]; - if (key && key != baseKey && ((keyMods & neededMods) == neededMods)) - result << int(key + (keyMods & ~neededMods)); + if (key && key != baseKey && ((keyMods & neededMods) == neededMods)) { + const Qt::KeyboardModifiers missingMods = keyMods & ~neededMods; + const int matchedKey = int(key) + missingMods; + const QList<int>::iterator it = + std::find_if(result.begin(), result.end(), + [key] (int k) { return (k & ~Qt::KeyboardModifierMask) == key; }); + // QTBUG-67200: Use the match with the least modifiers (prefer + // Shift+9 over Alt + Shift + 9) resulting in more missing modifiers. + if (it == result.end()) + result << matchedKey; + else if (missingMods > (*it & Qt::KeyboardModifierMask)) + *it = matchedKey; + } } return result; diff --git a/src/plugins/platforms/windows/qwindowskeymapper.h b/src/plugins/platforms/windows/qwindowskeymapper.h index 2657644780..c6b46b0c30 100644 --- a/src/plugins/platforms/windows/qwindowskeymapper.h +++ b/src/plugins/platforms/windows/qwindowskeymapper.h @@ -90,7 +90,7 @@ public: QList<int> possibleKeys(const QKeyEvent *e) const; private: - bool translateKeyEventInternal(QWindow *receiver, const MSG &msg, bool grab); + bool translateKeyEventInternal(QWindow *receiver, const MSG &msg, bool grab, LRESULT *lResult); bool translateMultimediaKeyEventInternal(QWindow *receiver, const MSG &msg); void updateKeyMap(const MSG &msg); diff --git a/src/plugins/platforms/windows/qwindowsmenu.cpp b/src/plugins/platforms/windows/qwindowsmenu.cpp index b89e1b66a3..71802b9017 100644 --- a/src/plugins/platforms/windows/qwindowsmenu.cpp +++ b/src/plugins/platforms/windows/qwindowsmenu.cpp @@ -390,6 +390,7 @@ void QWindowsMenuItem::setChecked(bool isChecked) menuItemSetChangeState(parentMenuHandle(), m_id, FALSE, m_checked, MF_CHECKED, MF_UNCHECKED); } +#if QT_CONFIG(shortcut) void QWindowsMenuItem::setShortcut(const QKeySequence &shortcut) { qCDebug(lcQpaMenus) << __FUNCTION__ << '(' << shortcut << ')' << this; @@ -399,6 +400,7 @@ void QWindowsMenuItem::setShortcut(const QKeySequence &shortcut) if (m_parentMenu != nullptr) updateText(); } +#endif void QWindowsMenuItem::setEnabled(bool enabled) { @@ -441,10 +443,12 @@ UINT QWindowsMenuItem::state() const QString QWindowsMenuItem::nativeText() const { QString result = m_text; +#if QT_CONFIG(shortcut) if (!m_shortcut.isEmpty()) { result += QLatin1Char('\t'); result += m_shortcut.toString(QKeySequence::NativeText); } +#endif return result; } @@ -894,8 +898,10 @@ void QWindowsMenuItem::formatDebug(QDebug &d) const d << ", subMenu=" << static_cast<const void *>(m_subMenu); d << ", tag=" << showbase << hex << tag() << noshowbase << dec << ", id=" << m_id; +#if QT_CONFIG(shortcut) if (!m_shortcut.isEmpty()) d << ", shortcut=" << m_shortcut; +#endif if (m_visible) d << " [visible]"; if (m_enabled) diff --git a/src/plugins/platforms/windows/qwindowsmousehandler.cpp b/src/plugins/platforms/windows/qwindowsmousehandler.cpp index 814291c54a..17851618b4 100644 --- a/src/plugins/platforms/windows/qwindowsmousehandler.cpp +++ b/src/plugins/platforms/windows/qwindowsmousehandler.cpp @@ -395,10 +395,24 @@ static bool isValidWheelReceiver(QWindow *candidate) static void redirectWheelEvent(QWindow *window, const QPoint &globalPos, int delta, Qt::Orientation orientation, Qt::KeyboardModifiers mods) { + // Redirect wheel event to one of the following, in order of preference: + // 1) The window under mouse + // 2) The window receiving the event // If a window is blocked by modality, it can't get the event. - if (isValidWheelReceiver(window)) { - QWindowSystemInterface::handleWheelEvent(window, - QWindowsGeometryHint::mapFromGlobal(window, globalPos), + + QWindow *receiver = QWindowsScreen::windowAt(globalPos, CWP_SKIPINVISIBLE); + while (receiver && receiver->flags().testFlag(Qt::WindowTransparentForInput)) + receiver = receiver->parent(); + bool handleEvent = true; + if (!isValidWheelReceiver(receiver)) { + receiver = window; + if (!isValidWheelReceiver(receiver)) + handleEvent = false; + } + + if (handleEvent) { + QWindowSystemInterface::handleWheelEvent(receiver, + QWindowsGeometryHint::mapFromGlobal(receiver, globalPos), globalPos, delta, orientation, mods); } } diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index f1762146ec..f8d6ae222e 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -1144,11 +1144,11 @@ void QWindowsWindow::initialize() const Qt::WindowState state = w->windowState(); if (state != Qt::WindowMaximized && state != Qt::WindowFullScreen && creationContext->requestedGeometryIn != creationContext->obtainedGeometry) { - QWindowSystemInterface::handleGeometryChange(w, creationContext->obtainedGeometry); + QWindowSystemInterface::handleGeometryChange<QWindowSystemInterface::SynchronousDelivery>(w, creationContext->obtainedGeometry); } QPlatformScreen *obtainedScreen = screenForGeometry(creationContext->obtainedGeometry); if (obtainedScreen && screen() != obtainedScreen) - QWindowSystemInterface::handleWindowScreenChanged(w, obtainedScreen->screen()); + QWindowSystemInterface::handleWindowScreenChanged<QWindowSystemInterface::SynchronousDelivery>(w, obtainedScreen->screen()); } } diff --git a/src/plugins/platforms/xcb/qxcbcursor.cpp b/src/plugins/platforms/xcb/qxcbcursor.cpp index 8d151b760b..b401100dd4 100644 --- a/src/plugins/platforms/xcb/qxcbcursor.cpp +++ b/src/plugins/platforms/xcb/qxcbcursor.cpp @@ -301,8 +301,10 @@ QXcbCursorCacheKey::QXcbCursorCacheKey(const QCursor &c) QXcbCursor::QXcbCursor(QXcbConnection *conn, QXcbScreen *screen) : QXcbObject(conn), m_screen(screen), m_gtkCursorThemeInitialized(false) { +#if QT_CONFIG(cursor) // see NUM_BITMAPS in libXcursor/src/xcursorint.h m_bitmapCache.setMaxCost(8); +#endif if (cursorCount++) return; diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp index df458e85d7..e1bd8eb752 100644 --- a/src/plugins/platforms/xcb/qxcbscreen.cpp +++ b/src/plugins/platforms/xcb/qxcbscreen.cpp @@ -750,7 +750,12 @@ void QXcbScreen::updateGeometry(const QRect &geometry, uint8_t rotation) m_sizeMillimeters = sizeInMillimeters(geometry.size(), virtualDpi()); qreal dpi = geometry.width() / physicalSize().width() * qreal(25.4); - m_pixelDensity = qMax(1, qRound(dpi/96)); + qreal rawFactor = dpi/96; + int roundedFactor = qFloor(rawFactor); + // Round up for .8 and higher. This favors "small UI" over "large UI". + if (rawFactor - roundedFactor >= 0.8) + roundedFactor = qCeil(rawFactor); + m_pixelDensity = qMax(1, roundedFactor); m_geometry = geometry; m_availableGeometry = geometry & m_virtualDesktop->workArea(); QWindowSystemInterface::handleScreenGeometryChange(QPlatformScreen::screen(), m_geometry, m_availableGeometry); |