diff options
Diffstat (limited to 'src/plugins/platforms')
-rw-r--r-- | src/plugins/platforms/android/androidjniinput.cpp | 2 | ||||
-rw-r--r-- | src/plugins/platforms/android/androidjnimain.cpp | 5 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoawindow.mm | 5 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qnswindow.mm | 14 | ||||
-rw-r--r-- | src/plugins/platforms/ios/quiaccessibilityelement.mm | 13 | ||||
-rw-r--r-- | src/plugins/platforms/vnc/qvnc.cpp | 5 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbclipboard.cpp | 16 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbconnection.cpp | 8 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbconnection_basic.cpp | 8 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbeventqueue.cpp | 8 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbeventqueue.h | 4 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbwindow.cpp | 49 |
12 files changed, 101 insertions, 36 deletions
diff --git a/src/plugins/platforms/android/androidjniinput.cpp b/src/plugins/platforms/android/androidjniinput.cpp index 56885f2e23..6ba1aa5e24 100644 --- a/src/plugins/platforms/android/androidjniinput.cpp +++ b/src/plugins/platforms/android/androidjniinput.cpp @@ -519,7 +519,7 @@ namespace QtAndroidInput return Qt::Key_Search; case 0x00000055: // KEYCODE_MEDIA_PLAY_PAUSE - return Qt::Key_MediaPlay; + return Qt::Key_MediaTogglePlayPause; case 0x00000056: // KEYCODE_MEDIA_STOP return Qt::Key_MediaStop; diff --git a/src/plugins/platforms/android/androidjnimain.cpp b/src/plugins/platforms/android/androidjnimain.cpp index 74edfd8356..9ce3353040 100644 --- a/src/plugins/platforms/android/androidjnimain.cpp +++ b/src/plugins/platforms/android/androidjnimain.cpp @@ -505,7 +505,7 @@ static void waitForServiceSetup(JNIEnv *env, jclass /*clazz*/) QtAndroidPrivate::waitForServiceSetup(); } -static jboolean startQtApplication(JNIEnv */*env*/, jclass /*clazz*/) +static void startQtApplication(JNIEnv */*env*/, jclass /*clazz*/) { { JNIEnv* env = nullptr; @@ -540,7 +540,8 @@ static jboolean startQtApplication(JNIEnv */*env*/, jclass /*clazz*/) sem_destroy(&m_exitSemaphore); // We must call exit() to ensure that all global objects will be destructed - exit(ret); + if (!qEnvironmentVariableIsSet("QT_ANDROID_NO_EXIT_CALL")) + exit(ret); } static void quitQtCoreApplication(JNIEnv *env, jclass /*clazz*/) diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index 23c5a2fdda..2a23bf286f 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -500,7 +500,10 @@ NSUInteger QCocoaWindow::windowStyleMask(Qt::WindowFlags flags) NSUInteger styleMask = (frameless || !resizable) ? NSWindowStyleMaskBorderless : NSWindowStyleMaskResizable; if (frameless) { - // No further customizations for frameless since there are no window decorations. + // Frameless windows do not display the traffic lights buttons for + // e.g. minimize, however StyleMaskMiniaturizable is required to allow + // programatic minimize. + styleMask |= NSWindowStyleMaskMiniaturizable; } else if (flags & Qt::CustomizeWindowHint) { if (flags & Qt::WindowTitleHint) styleMask |= NSWindowStyleMaskTitled; diff --git a/src/plugins/platforms/cocoa/qnswindow.mm b/src/plugins/platforms/cocoa/qnswindow.mm index 1a74fd73f8..8cff444359 100644 --- a/src/plugins/platforms/cocoa/qnswindow.mm +++ b/src/plugins/platforms/cocoa/qnswindow.mm @@ -253,8 +253,18 @@ static bool isMouseEvent(NSEvent *ev) - (NSColor *)backgroundColor { - return self.styleMask == NSWindowStyleMaskBorderless ? - [NSColor clearColor] : [super backgroundColor]; + // FIXME: Plumb to a WA_NoSystemBackground-like window flag, + // or a QWindow::backgroundColor() property. In the meantime + // we assume that if you have translucent content, without a + // frame then you intend to do all background drawing yourself. + const QWindow *window = m_platformWindow ? m_platformWindow->window() : nullptr; + if (!self.opaque && window && window->flags().testFlag(Qt::FramelessWindowHint)) + return [NSColor clearColor]; + + // This still allows you to have translucent content with a frame, + // where the system background (or color set via NSWindow) will + // shine through. + return [super backgroundColor]; } - (void)sendEvent:(NSEvent*)theEvent diff --git a/src/plugins/platforms/ios/quiaccessibilityelement.mm b/src/plugins/platforms/ios/quiaccessibilityelement.mm index 3154536aad..4dd1f9f035 100644 --- a/src/plugins/platforms/ios/quiaccessibilityelement.mm +++ b/src/plugins/platforms/ios/quiaccessibilityelement.mm @@ -123,8 +123,7 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QMacAccessibilityElement); if (val) { return val->currentValue().toString().toNSString(); } else if (QAccessibleTextInterface *text = iface->textInterface()) { - // FIXME doesn't work? - return text->text(0, text->characterCount() - 1).toNSString(); + return text->text(0, text->characterCount()).toNSString(); } return [super accessibilityHint]; @@ -158,8 +157,16 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QMacAccessibilityElement); if (state.searchEdit) traits |= UIAccessibilityTraitSearchField; - if (iface->role() == QAccessible::Button) + const auto accessibleRole = iface->role(); + if (accessibleRole == QAccessible::Button) { traits |= UIAccessibilityTraitButton; + } else if (accessibleRole == QAccessible::EditableText) { + static auto defaultTextFieldTraits = []{ + auto *textField = [[[UITextField alloc] initWithFrame:CGRectZero] autorelease]; + return textField.accessibilityTraits; + }(); + traits |= defaultTextFieldTraits; + } if (iface->valueInterface()) traits |= UIAccessibilityTraitAdjustable; diff --git a/src/plugins/platforms/vnc/qvnc.cpp b/src/plugins/platforms/vnc/qvnc.cpp index ffe00de2b1..43fbc9daf7 100644 --- a/src/plugins/platforms/vnc/qvnc.cpp +++ b/src/plugins/platforms/vnc/qvnc.cpp @@ -477,6 +477,9 @@ void QRfbRawEncoder::write() // server->screen()->geometry().height()); // } + const QImage screenImage = client->server()->screenImage(); + rgn &= screenImage.rect(); + const auto rectsInRegion = rgn.rectCount(); { @@ -492,8 +495,6 @@ void QRfbRawEncoder::write() if (rectsInRegion <= 0) return; - const QImage screenImage = client->server()->screenImage(); - for (const QRect &tileRect: rgn) { const QRfbRect rect(tileRect.x(), tileRect.y(), tileRect.width(), tileRect.height()); diff --git a/src/plugins/platforms/xcb/qxcbclipboard.cpp b/src/plugins/platforms/xcb/qxcbclipboard.cpp index ac8b029916..a4940f1c49 100644 --- a/src/plugins/platforms/xcb/qxcbclipboard.cpp +++ b/src/plugins/platforms/xcb/qxcbclipboard.cpp @@ -787,6 +787,12 @@ xcb_generic_event_t *QXcbClipboard::waitForClipboardEvent(xcb_window_t window, i if (e) // found the waited for event return e; + // It is safe to assume here that the pointed to node won't be re-used + // while we are holding the pointer to it. The nodes can be recycled + // only when they are dequeued, which is done only by + // QXcbConnection::processXcbEvents(). + const QXcbEventNode *flushedTailNode = queue->flushedTail(); + if (checkManager) { auto reply = Q_XCB_REPLY(xcb_get_selection_owner, xcb_connection(), atom(QXcbAtom::CLIPBOARD_MANAGER)); if (!reply || reply->owner == XCB_NONE) @@ -812,7 +818,7 @@ xcb_generic_event_t *QXcbClipboard::waitForClipboardEvent(xcb_window_t window, i const auto elapsed = timer.elapsed(); if (elapsed < clipboard_timeout) - queue->waitForNewEvents(clipboard_timeout - elapsed); + queue->waitForNewEvents(flushedTailNode, clipboard_timeout - elapsed); } while (timer.elapsed() < clipboard_timeout); return nullptr; @@ -835,6 +841,8 @@ QByteArray QXcbClipboard::clipboardReadIncrementalProperty(xcb_window_t win, xcb alloc_error = buf.size() != nbytes+1; } + QElapsedTimer timer; + timer.start(); for (;;) { connection()->flush(); xcb_generic_event_t *ge = waitForClipboardEvent(win, XCB_PROPERTY_NOTIFY); @@ -870,9 +878,11 @@ QByteArray QXcbClipboard::clipboardReadIncrementalProperty(xcb_window_t win, xcb tmp_buf.resize(0); offset += length; } - } else { - break; } + + const auto elapsed = timer.elapsed(); + if (elapsed > clipboard_timeout) + break; } // timed out ... create a new requestor window, otherwise the requestor diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index a563bf6005..8f0281c176 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -806,7 +806,13 @@ xcb_timestamp_t QXcbConnection::getTimestamp() xcb_window_t QXcbConnection::getSelectionOwner(xcb_atom_t atom) const { - return Q_XCB_REPLY(xcb_get_selection_owner, xcb_connection(), atom)->owner; + auto reply = Q_XCB_REPLY(xcb_get_selection_owner, xcb_connection(), atom); + if (!reply) { + qCDebug(lcQpaXcb) << "failed to query selection owner"; + return XCB_NONE; + } + + return reply->owner; } xcb_window_t QXcbConnection::getQtSelectionOwner() diff --git a/src/plugins/platforms/xcb/qxcbconnection_basic.cpp b/src/plugins/platforms/xcb/qxcbconnection_basic.cpp index af72285135..bdd7e2d98a 100644 --- a/src/plugins/platforms/xcb/qxcbconnection_basic.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection_basic.cpp @@ -183,7 +183,13 @@ xcb_atom_t QXcbBasicConnection::internAtom(const char *name) if (!name || *name == 0) return XCB_NONE; - return Q_XCB_REPLY(xcb_intern_atom, m_xcbConnection, false, strlen(name), name)->atom; + auto reply = Q_XCB_REPLY(xcb_intern_atom, m_xcbConnection, false, strlen(name), name); + if (!reply) { + qCDebug(lcQpaXcb) << "failed to query intern atom: " << name; + return XCB_NONE; + } + + return reply->atom; } QByteArray QXcbBasicConnection::atomName(xcb_atom_t atom) diff --git a/src/plugins/platforms/xcb/qxcbeventqueue.cpp b/src/plugins/platforms/xcb/qxcbeventqueue.cpp index 4ca73e3048..b96bda3194 100644 --- a/src/plugins/platforms/xcb/qxcbeventqueue.cpp +++ b/src/plugins/platforms/xcb/qxcbeventqueue.cpp @@ -226,6 +226,8 @@ void QXcbEventQueue::run() }; while (!m_closeConnectionDetected && (event = xcb_wait_for_event(connection))) { + // This lock can block only if there are users of waitForNewEvents(). + // Currently only the clipboard implementation relies on it. m_newEventsMutex.lock(); enqueueEvent(event); while (!m_closeConnectionDetected && (event = xcb_poll_for_queued_event(connection))) @@ -350,12 +352,12 @@ bool QXcbEventQueue::peekEventQueue(PeekerCallback peeker, void *peekerData, return result; } -void QXcbEventQueue::waitForNewEvents(unsigned long time) +void QXcbEventQueue::waitForNewEvents(const QXcbEventNode *sinceFlushedTail, + unsigned long time) { QMutexLocker locker(&m_newEventsMutex); - QXcbEventNode *tailBeforeFlush = m_flushedTail; flushBufferedEvents(); - if (tailBeforeFlush != m_flushedTail) + if (sinceFlushedTail != m_flushedTail) return; m_newEventsCondition.wait(&m_newEventsMutex, time); } diff --git a/src/plugins/platforms/xcb/qxcbeventqueue.h b/src/plugins/platforms/xcb/qxcbeventqueue.h index 11d0b8e963..c8f09ed9e3 100644 --- a/src/plugins/platforms/xcb/qxcbeventqueue.h +++ b/src/plugins/platforms/xcb/qxcbeventqueue.h @@ -106,7 +106,9 @@ public: bool peekEventQueue(PeekerCallback peeker, void *peekerData = nullptr, PeekOptions option = PeekDefault, qint32 peekerId = -1); - void waitForNewEvents(unsigned long time = ULONG_MAX); + const QXcbEventNode *flushedTail() const { return m_flushedTail; } + void waitForNewEvents(const QXcbEventNode *sinceFlushedTail, + unsigned long time = ULONG_MAX); private: QXcbEventNode *qXcbEventNodeFactory(xcb_generic_event_t *event); diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index d7d5bd3958..a6d2054110 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -1172,27 +1172,44 @@ void QXcbWindow::setWindowState(Qt::WindowStates state) if (state == m_windowState) return; - if ((m_windowState & Qt::WindowMinimized) && !(state & Qt::WindowMinimized)) { + // unset old state + if (m_windowState & Qt::WindowMinimized) xcb_map_window(xcb_connection(), m_window); - } else if (!(m_windowState & Qt::WindowMinimized) && (state & Qt::WindowMinimized)) { - xcb_client_message_event_t event; + if (m_windowState & Qt::WindowMaximized) + setNetWmState(false, + atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_HORZ), + atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_VERT)); + if (m_windowState & Qt::WindowFullScreen) + setNetWmState(false, atom(QXcbAtom::_NET_WM_STATE_FULLSCREEN)); - event.response_type = XCB_CLIENT_MESSAGE; - event.format = 32; - event.sequence = 0; - event.window = m_window; - event.type = atom(QXcbAtom::WM_CHANGE_STATE); - event.data.data32[0] = XCB_ICCCM_WM_STATE_ICONIC; - event.data.data32[1] = 0; - event.data.data32[2] = 0; - event.data.data32[3] = 0; - event.data.data32[4] = 0; + // set new state + if (state & Qt::WindowMinimized) { + { + xcb_client_message_event_t event; + + event.response_type = XCB_CLIENT_MESSAGE; + event.format = 32; + event.sequence = 0; + event.window = m_window; + event.type = atom(QXcbAtom::WM_CHANGE_STATE); + event.data.data32[0] = XCB_ICCCM_WM_STATE_ICONIC; + event.data.data32[1] = 0; + event.data.data32[2] = 0; + event.data.data32[3] = 0; + event.data.data32[4] = 0; - xcb_send_event(xcb_connection(), 0, xcbScreen()->root(), - XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, - (const char *)&event); + xcb_send_event(xcb_connection(), 0, xcbScreen()->root(), + XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, + (const char *)&event); + } m_minimized = true; } + if (state & Qt::WindowMaximized) + setNetWmState(true, + atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_HORZ), + atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_VERT)); + if (state & Qt::WindowFullScreen) + setNetWmState(true, atom(QXcbAtom::_NET_WM_STATE_FULLSCREEN)); setNetWmState(state); |