summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/platforms')
-rw-r--r--src/plugins/platforms/android/androidjniinput.cpp2
-rw-r--r--src/plugins/platforms/android/androidjnimain.cpp5
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.mm5
-rw-r--r--src/plugins/platforms/cocoa/qnswindow.mm14
-rw-r--r--src/plugins/platforms/ios/quiaccessibilityelement.mm13
-rw-r--r--src/plugins/platforms/vnc/qvnc.cpp5
-rw-r--r--src/plugins/platforms/xcb/qxcbclipboard.cpp16
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.cpp8
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection_basic.cpp8
-rw-r--r--src/plugins/platforms/xcb/qxcbeventqueue.cpp8
-rw-r--r--src/plugins/platforms/xcb/qxcbeventqueue.h4
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.cpp49
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);