summaryrefslogtreecommitdiffstats
path: root/src/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins')
-rw-r--r--src/plugins/platforms/cocoa/qcocoaintegration.mm9
-rw-r--r--src/plugins/platforms/cocoa/qnsview.mm15
-rw-r--r--src/plugins/platforms/cocoa/qnsview_drawing.mm61
-rw-r--r--src/plugins/platforms/eglfs/api/qeglfsintegration.cpp1
-rw-r--r--src/plugins/platforms/eglfs/api/qeglfsscreen.cpp10
-rw-r--r--src/plugins/platforms/minimalegl/qminimaleglintegration.cpp1
-rw-r--r--src/plugins/platforms/windows/qwindowsinputcontext.cpp13
-rw-r--r--src/plugins/platforms/windows/qwindowspointerhandler.cpp58
-rw-r--r--src/plugins/platforms/windows/qwindowspointerhandler.h1
9 files changed, 122 insertions, 47 deletions
diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm
index 936fecf8de..1bd1029863 100644
--- a/src/plugins/platforms/cocoa/qcocoaintegration.mm
+++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm
@@ -340,12 +340,17 @@ QCocoaScreen *QCocoaIntegration::screenForNSScreen(NSScreen *nsScreen)
bool QCocoaIntegration::hasCapability(QPlatformIntegration::Capability cap) const
{
switch (cap) {
- case ThreadedPixmaps:
#ifndef QT_NO_OPENGL
- case OpenGL:
case ThreadedOpenGL:
+ // AppKit expects rendering to happen on the main thread, and we can
+ // easily end up in situations where rendering on secondary threads
+ // will result in visual artifacts, bugs, or even deadlocks, when
+ // building with SDK 10.14 or higher which enbles view layer-backing.
+ return QMacVersion::buildSDK() < QOperatingSystemVersion(QOperatingSystemVersion::MacOSMojave);
+ case OpenGL:
case BufferQueueingOpenGL:
#endif
+ case ThreadedPixmaps:
case WindowMasks:
case MultipleWindows:
case ForeignWindows:
diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm
index 9bd53ed334..540f701d43 100644
--- a/src/plugins/platforms/cocoa/qnsview.mm
+++ b/src/plugins/platforms/cocoa/qnsview.mm
@@ -71,7 +71,7 @@
@end
@interface QT_MANGLE_NAMESPACE(QNSView) (Drawing) <CALayerDelegate>
-- (BOOL)wantsLayerHelper;
+- (void)initDrawing;
@end
@interface QT_MANGLE_NAMESPACE(QNSViewMouseMoveHelper) : NSObject
@@ -152,19 +152,8 @@
self.focusRingType = NSFocusRingTypeNone;
self.cursor = nil;
- self.wantsLayer = [self wantsLayerHelper];
-
- // Enable high-DPI OpenGL for retina displays. Enabling has the side
- // effect that Cocoa will start calling glViewport(0, 0, width, height),
- // overriding any glViewport calls in application code. This is usually not a
- // problem, except if the application wants to have a "custom" viewport.
- // (like the hellogl example)
- if (m_platformWindow->window()->supportsOpenGL()) {
- self.wantsBestResolutionOpenGLSurface = qt_mac_resolveOption(YES, m_platformWindow->window(),
- "_q_mac_wantsBestResolutionOpenGLSurface", "QT_MAC_WANTS_BEST_RESOLUTION_OPENGL_SURFACE");
- // See also QCocoaGLContext::makeCurrent for software renderer workarounds.
- }
+ [self initDrawing];
[self registerDragTypes];
[[NSNotificationCenter defaultCenter] addObserver:self
diff --git a/src/plugins/platforms/cocoa/qnsview_drawing.mm b/src/plugins/platforms/cocoa/qnsview_drawing.mm
index 4f9d17504d..e9af90a45c 100644
--- a/src/plugins/platforms/cocoa/qnsview_drawing.mm
+++ b/src/plugins/platforms/cocoa/qnsview_drawing.mm
@@ -41,6 +41,24 @@
@implementation QT_MANGLE_NAMESPACE(QNSView) (Drawing)
+- (void)initDrawing
+{
+ self.wantsLayer = [self layerExplicitlyRequested]
+ || [self shouldUseMetalLayer]
+ || [self layerEnabledByMacOS];
+
+ // Enable high-DPI OpenGL for retina displays. Enabling has the side
+ // effect that Cocoa will start calling glViewport(0, 0, width, height),
+ // overriding any glViewport calls in application code. This is usually not a
+ // problem, except if the application wants to have a "custom" viewport.
+ // (like the hellogl example)
+ if (m_platformWindow->window()->supportsOpenGL()) {
+ self.wantsBestResolutionOpenGLSurface = qt_mac_resolveOption(YES, m_platformWindow->window(),
+ "_q_mac_wantsBestResolutionOpenGLSurface", "QT_MAC_WANTS_BEST_RESOLUTION_OPENGL_SURFACE");
+ // See also QCocoaGLContext::makeCurrent for software renderer workarounds.
+ }
+}
+
- (BOOL)isOpaque
{
if (!m_platformWindow)
@@ -71,23 +89,38 @@
m_platformWindow->handleExposeEvent(exposedRegion);
}
-- (BOOL)shouldUseMetalLayer
+- (BOOL)layerEnabledByMacOS
{
- // MetalSurface needs a layer, and so does VulkanSurface (via MoltenVK)
- QSurface::SurfaceType surfaceType = m_platformWindow->window()->surfaceType();
- return surfaceType == QWindow::MetalSurface || surfaceType == QWindow::VulkanSurface;
+ // AppKit has its own logic for this, but if we rely on that, our layers are created
+ // by AppKit at a point where we've already set up other parts of the platform plugin
+ // based on the presence of layers or not. Once we've rewritten these parts to support
+ // dynamically picking up layer enablement we can let AppKit do its thing.
+ return QMacVersion::buildSDK() >= QOperatingSystemVersion::MacOSMojave
+ && QMacVersion::currentRuntime() >= QOperatingSystemVersion::MacOSMojave;
}
-- (BOOL)wantsLayerHelper
+- (BOOL)layerExplicitlyRequested
{
- Q_ASSERT(m_platformWindow);
+ static bool wantsLayer = [&]() {
+ int wantsLayer = qt_mac_resolveOption(-1, m_platformWindow->window(),
+ "_q_mac_wantsLayer", "QT_MAC_WANTS_LAYER");
- bool wantsLayer = qt_mac_resolveOption(true, m_platformWindow->window(),
- "_q_mac_wantsLayer", "QT_MAC_WANTS_LAYER");
+ if (wantsLayer != -1 && [self layerEnabledByMacOS]) {
+ qCWarning(lcQpaDrawing) << "Layer-backing can not be explicitly controlled on 10.14 when built against the 10.14 SDK";
+ return true;
+ }
- bool layerForSurfaceType = [self shouldUseMetalLayer];
+ return wantsLayer == 1;
+ }();
- return wantsLayer || layerForSurfaceType;
+ return wantsLayer;
+}
+
+- (BOOL)shouldUseMetalLayer
+{
+ // MetalSurface needs a layer, and so does VulkanSurface (via MoltenVK)
+ QSurface::SurfaceType surfaceType = m_platformWindow->window()->surfaceType();
+ return surfaceType == QWindow::MetalSurface || surfaceType == QWindow::VulkanSurface;
}
- (CALayer *)makeBackingLayer
@@ -115,6 +148,14 @@
return [super makeBackingLayer];
}
+- (void)setLayer:(CALayer *)layer
+{
+ qCDebug(lcQpaDrawing) << "Making" << self << "layer-backed with" << layer
+ << "due to being" << ([self layerExplicitlyRequested] ? "explicitly requested"
+ : [self shouldUseMetalLayer] ? "needed by surface type" : "enabled by macOS");
+ [super setLayer:layer];
+}
+
- (NSViewLayerContentsRedrawPolicy)layerContentsRedrawPolicy
{
// We need to set this explicitly since the super implementation
diff --git a/src/plugins/platforms/eglfs/api/qeglfsintegration.cpp b/src/plugins/platforms/eglfs/api/qeglfsintegration.cpp
index 43f2e31a49..72420199e3 100644
--- a/src/plugins/platforms/eglfs/api/qeglfsintegration.cpp
+++ b/src/plugins/platforms/eglfs/api/qeglfsintegration.cpp
@@ -198,6 +198,7 @@ QPlatformBackingStore *QEglFSIntegration::createPlatformBackingStore(QWindow *wi
static_cast<QEglFSWindow *>(window->handle())->setBackingStore(bs);
return bs;
#else
+ Q_UNUSED(window);
return nullptr;
#endif
}
diff --git a/src/plugins/platforms/eglfs/api/qeglfsscreen.cpp b/src/plugins/platforms/eglfs/api/qeglfsscreen.cpp
index d5c22b3d37..285dbd93d3 100644
--- a/src/plugins/platforms/eglfs/api/qeglfsscreen.cpp
+++ b/src/plugins/platforms/eglfs/api/qeglfsscreen.cpp
@@ -183,6 +183,8 @@ void QEglFSScreen::handleCursorMove(const QPoint &pos)
if (enter && leave)
QWindowSystemInterface::handleEnterLeaveEvent(enter, leave, enter->mapFromGlobal(pos), pos);
+#else
+ Q_UNUSED(pos);
#endif
}
@@ -231,7 +233,13 @@ QPixmap QEglFSScreen::grabWindow(WId wid, int x, int y, int width, int height) c
return QPixmap::fromImage(img).copy(rect);
}
}
-#endif // QT_NO_OPENGL
+#else // QT_NO_OPENGL
+ Q_UNUSED(wid);
+ Q_UNUSED(x);
+ Q_UNUSED(y);
+ Q_UNUSED(width);
+ Q_UNUSED(height);
+#endif
return QPixmap();
}
diff --git a/src/plugins/platforms/minimalegl/qminimaleglintegration.cpp b/src/plugins/platforms/minimalegl/qminimaleglintegration.cpp
index 5d31af53d5..da58441d67 100644
--- a/src/plugins/platforms/minimalegl/qminimaleglintegration.cpp
+++ b/src/plugins/platforms/minimalegl/qminimaleglintegration.cpp
@@ -132,6 +132,7 @@ QPlatformBackingStore *QMinimalEglIntegration::createPlatformBackingStore(QWindo
#ifndef QT_NO_OPENGL
return new QMinimalEglBackingStore(window);
#else
+ Q_UNUSED(window);
return nullptr;
#endif
}
diff --git a/src/plugins/platforms/windows/qwindowsinputcontext.cpp b/src/plugins/platforms/windows/qwindowsinputcontext.cpp
index 30da0da1de..d1e99c037b 100644
--- a/src/plugins/platforms/windows/qwindowsinputcontext.cpp
+++ b/src/plugins/platforms/windows/qwindowsinputcontext.cpp
@@ -242,7 +242,18 @@ QRectF QWindowsInputContext::keyboardRect() const
bool QWindowsInputContext::isInputPanelVisible() const
{
HWND hwnd = getVirtualKeyboardWindowHandle();
- return hwnd && ::IsWindowEnabled(hwnd) && ::IsWindowVisible(hwnd);
+ if (hwnd && ::IsWindowEnabled(hwnd) && ::IsWindowVisible(hwnd))
+ return true;
+ // check if the Input Method Editor is open
+ if (inputMethodAccepted()) {
+ if (QWindow *window = QGuiApplication::focusWindow()) {
+ if (QWindowsWindow *platformWindow = QWindowsWindow::windowsWindowOf(window)) {
+ if (HIMC himc = ImmGetContext(platformWindow->handle()))
+ return ImmGetOpenStatus(himc);
+ }
+ }
+ }
+ return false;
}
void QWindowsInputContext::showInputPanel()
diff --git a/src/plugins/platforms/windows/qwindowspointerhandler.cpp b/src/plugins/platforms/windows/qwindowspointerhandler.cpp
index d88049019b..0bac382a90 100644
--- a/src/plugins/platforms/windows/qwindowspointerhandler.cpp
+++ b/src/plugins/platforms/windows/qwindowspointerhandler.cpp
@@ -336,6 +336,38 @@ static void getMouseEventInfo(UINT message, POINTER_BUTTON_CHANGE_TYPE changeTyp
*mouseButton = buttonMapping.value(changeType, Qt::NoButton);
}
+static Qt::MouseButtons mouseButtonsFromPointerFlags(POINTER_FLAGS pointerFlags)
+{
+ Qt::MouseButtons result = Qt::NoButton;
+ if (pointerFlags & POINTER_FLAG_FIRSTBUTTON)
+ result |= Qt::LeftButton;
+ if (pointerFlags & POINTER_FLAG_SECONDBUTTON)
+ result |= Qt::RightButton;
+ if (pointerFlags & POINTER_FLAG_THIRDBUTTON)
+ result |= Qt::MiddleButton;
+ if (pointerFlags & POINTER_FLAG_FOURTHBUTTON)
+ result |= Qt::XButton1;
+ if (pointerFlags & POINTER_FLAG_FIFTHBUTTON)
+ result |= Qt::XButton2;
+ return result;
+}
+
+static Qt::MouseButtons mouseButtonsFromKeyState(WPARAM keyState)
+{
+ Qt::MouseButtons result = Qt::NoButton;
+ if (keyState & MK_LBUTTON)
+ result |= Qt::LeftButton;
+ if (keyState & MK_RBUTTON)
+ result |= Qt::RightButton;
+ if (keyState & MK_MBUTTON)
+ result |= Qt::MiddleButton;
+ if (keyState & MK_XBUTTON1)
+ result |= Qt::XButton1;
+ if (keyState & MK_XBUTTON2)
+ result |= Qt::XButton2;
+ return result;
+}
+
static QWindow *getWindowUnderPointer(QWindow *window, QPoint globalPos)
{
QWindow *currentWindowUnderPointer = QWindowsScreen::windowAt(globalPos, CWP_SKIPINVISIBLE | CWP_SKIPTRANSPARENT);
@@ -405,23 +437,6 @@ QTouchDevice *QWindowsPointerHandler::ensureTouchDevice()
return m_touchDevice;
}
-Qt::MouseButtons QWindowsPointerHandler::queryMouseButtons()
-{
- Qt::MouseButtons result = 0;
- const bool mouseSwapped = GetSystemMetrics(SM_SWAPBUTTON);
- if (GetAsyncKeyState(VK_LBUTTON) < 0)
- result |= mouseSwapped ? Qt::RightButton: Qt::LeftButton;
- if (GetAsyncKeyState(VK_RBUTTON) < 0)
- result |= mouseSwapped ? Qt::LeftButton : Qt::RightButton;
- if (GetAsyncKeyState(VK_MBUTTON) < 0)
- result |= Qt::MidButton;
- if (GetAsyncKeyState(VK_XBUTTON1) < 0)
- result |= Qt::XButton1;
- if (GetAsyncKeyState(VK_XBUTTON2) < 0)
- result |= Qt::XButton2;
- return result;
-}
-
bool QWindowsPointerHandler::translateMouseTouchPadEvent(QWindow *window, HWND hwnd,
QtWindows::WindowsEventType et,
MSG msg, PVOID vPointerInfo)
@@ -430,7 +445,7 @@ bool QWindowsPointerHandler::translateMouseTouchPadEvent(QWindow *window, HWND h
const QPoint globalPos = QPoint(pointerInfo->ptPixelLocation.x, pointerInfo->ptPixelLocation.y);
const QPoint localPos = QWindowsGeometryHint::mapFromGlobal(hwnd, globalPos);
const Qt::KeyboardModifiers keyModifiers = QWindowsKeyMapper::queryKeyboardModifiers();
- const Qt::MouseButtons mouseButtons = queryMouseButtons();
+ const Qt::MouseButtons mouseButtons = mouseButtonsFromPointerFlags(pointerInfo->pointerFlags);
QWindow *currentWindowUnderPointer = getWindowUnderPointer(window, globalPos);
QWindowsWindow *platformWindow = static_cast<QWindowsWindow *>(window->handle());
@@ -452,6 +467,11 @@ bool QWindowsPointerHandler::translateMouseTouchPadEvent(QWindow *window, HWND h
keyModifiers, Qt::MouseEventNotSynthesized);
return false; // To allow window dragging, etc.
} else {
+ if (eventType == QEvent::MouseButtonPress) {
+ // Implement "Click to focus" for native child windows (unless it is a native widget window).
+ if (!window->isTopLevel() && !window->inherits("QWidgetWindow") && QGuiApplication::focusWindow() != window)
+ window->requestActivate();
+ }
if (currentWindowUnderPointer != m_windowUnderPointer) {
if (m_windowUnderPointer && m_windowUnderPointer == m_currentWindow) {
QWindowSystemInterface::handleLeaveEvent(m_windowUnderPointer);
@@ -797,7 +817,7 @@ bool QWindowsPointerHandler::translateMouseEvent(QWindow *window, HWND hwnd, QtW
m_windowUnderPointer = currentWindowUnderPointer;
}
- const Qt::MouseButtons mouseButtons = queryMouseButtons();
+ const Qt::MouseButtons mouseButtons = mouseButtonsFromKeyState(msg.wParam);
if (!discardEvent)
QWindowSystemInterface::handleMouseEvent(window, localPos, globalPos, mouseButtons, Qt::NoButton, QEvent::MouseMove,
diff --git a/src/plugins/platforms/windows/qwindowspointerhandler.h b/src/plugins/platforms/windows/qwindowspointerhandler.h
index c4d0e0ce4a..3861ebf919 100644
--- a/src/plugins/platforms/windows/qwindowspointerhandler.h
+++ b/src/plugins/platforms/windows/qwindowspointerhandler.h
@@ -61,7 +61,6 @@ public:
bool translateMouseEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et, MSG msg, LRESULT *result);
QTouchDevice *touchDevice() const { return m_touchDevice; }
QTouchDevice *ensureTouchDevice();
- Qt::MouseButtons queryMouseButtons();
QWindow *windowUnderMouse() const { return m_windowUnderPointer.data(); }
void clearWindowUnderMouse() { m_windowUnderPointer = nullptr; }