summaryrefslogtreecommitdiffstats
path: root/src/plugins
diff options
context:
space:
mode:
authorSergio Ahumada <sahumada@blackberry.com>2014-06-11 20:11:59 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2014-06-11 23:06:01 +0200
commit490e79e39ee90ad89bac164891177160d1926fdf (patch)
treef6e993c617f81ccd75563e1ceeef5ee5efd1b818 /src/plugins
parenta6d7e09e89a73b3706aabbf2d08586f238348c7c (diff)
parent7ffbfed7c791b1c8e514b5c9d24e8b80de3f21c2 (diff)
Merge "Merge remote-tracking branch 'origin/stable' into 5.3" into refs/staging/5.3
Diffstat (limited to 'src/plugins')
-rw-r--r--src/plugins/platforms/android/androidjniaccessibility.cpp13
-rw-r--r--src/plugins/platforms/android/androidjnimain.cpp17
-rw-r--r--src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm9
-rw-r--r--src/plugins/platforms/cocoa/qcocoaintegration.mm41
-rw-r--r--src/plugins/platforms/eglfs/qeglfswindow.h2
-rw-r--r--src/plugins/platforms/ios/qiosinputcontext.mm10
-rw-r--r--src/plugins/platforms/ios/quiview.h1
-rw-r--r--src/plugins/platforms/ios/quiview_textinput.mm89
-rw-r--r--src/plugins/platforms/windows/accessible/iaccessible2.cpp1
-rw-r--r--src/plugins/platforms/windows/qwindowskeymapper.cpp1
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.cpp34
11 files changed, 145 insertions, 73 deletions
diff --git a/src/plugins/platforms/android/androidjniaccessibility.cpp b/src/plugins/platforms/android/androidjniaccessibility.cpp
index d9f5cec27a..9d43c2f758 100644
--- a/src/plugins/platforms/android/androidjniaccessibility.cpp
+++ b/src/plugins/platforms/android/androidjniaccessibility.cpp
@@ -47,6 +47,7 @@
#include "qwindow.h"
#include "qrect.h"
#include "QtGui/qaccessible.h"
+#include <QtCore/private/qjnihelpers_p.h>
#include "qdebug.h"
@@ -207,7 +208,7 @@ if (!clazz) { \
if (desc.isEmpty())
desc = iface->text(QAccessible::Description);
if (QAccessibleTextInterface *textIface = iface->textInterface()) {
- if (textIface->selectionCount() > 0) {
+ if (m_setTextSelectionMethodID && textIface->selectionCount() > 0) {
int startSelection;
int endSelection;
textIface->selection(0, &startSelection, &endSelection);
@@ -259,12 +260,15 @@ if (!clazz) { \
bool registerNatives(JNIEnv *env)
{
+ if (QtAndroidPrivate::androidSdkVersion() < 16)
+ return true; // We need API level 16 or higher
+
jclass clazz;
FIND_AND_CHECK_CLASS("org/qtproject/qt5/android/accessibility/QtNativeAccessibility");
jclass appClass = static_cast<jclass>(env->NewGlobalRef(clazz));
if (env->RegisterNatives(appClass, methods, sizeof(methods) / sizeof(methods[0])) < 0) {
- __android_log_print(ANDROID_LOG_FATAL,"Qt", "RegisterNatives failed");
+ __android_log_print(ANDROID_LOG_FATAL,"Qt A11y", "RegisterNatives failed");
return false;
}
@@ -277,9 +281,12 @@ if (!clazz) { \
GET_AND_CHECK_STATIC_METHOD(m_setEnabledMethodID, nodeInfoClass, "setEnabled", "(Z)V");
GET_AND_CHECK_STATIC_METHOD(m_setFocusableMethodID, nodeInfoClass, "setFocusable", "(Z)V");
GET_AND_CHECK_STATIC_METHOD(m_setFocusedMethodID, nodeInfoClass, "setFocused", "(Z)V");
- GET_AND_CHECK_STATIC_METHOD(m_setTextSelectionMethodID, nodeInfoClass, "setTextSelection", "(II)V");
GET_AND_CHECK_STATIC_METHOD(m_setVisibleToUserMethodID, nodeInfoClass, "setVisibleToUser", "(Z)V");
+ if (QtAndroidPrivate::androidSdkVersion() >= 18) {
+ GET_AND_CHECK_STATIC_METHOD(m_setTextSelectionMethodID, nodeInfoClass, "setTextSelection", "(II)V");
+ }
+
return true;
}
}
diff --git a/src/plugins/platforms/android/androidjnimain.cpp b/src/plugins/platforms/android/androidjnimain.cpp
index d484a2faff..f711a68a71 100644
--- a/src/plugins/platforms/android/androidjnimain.cpp
+++ b/src/plugins/platforms/android/androidjnimain.cpp
@@ -423,6 +423,7 @@ namespace QtAndroid
m_destroySurfaceMethodID,
surfaceId);
}
+
} // namespace QtAndroid
@@ -743,15 +744,6 @@ static int registerNatives(JNIEnv *env)
return JNI_TRUE;
}
-jint androidApiLevel(JNIEnv *env)
-{
- jclass clazz;
- FIND_AND_CHECK_CLASS("android/os/Build$VERSION");
- jfieldID fieldId;
- GET_AND_CHECK_STATIC_FIELD(fieldId, clazz, "SDK_INT", "I");
- return env->GetStaticIntField(clazz, fieldId);
-}
-
Q_DECL_EXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void */*reserved*/)
{
typedef union {
@@ -774,17 +766,12 @@ Q_DECL_EXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void */*reserved*/)
|| !QtAndroidInput::registerNatives(env)
|| !QtAndroidClipboard::registerNatives(env)
|| !QtAndroidMenu::registerNatives(env)
+ || !QtAndroidAccessibility::registerNatives(env)
|| !QtAndroidDialogHelpers::registerNatives(env)) {
__android_log_print(ANDROID_LOG_FATAL, "Qt", "registerNatives failed");
return -1;
}
- jint apiLevel = androidApiLevel(env);
- if (apiLevel >= 16 && !QtAndroidAccessibility::registerNatives(env)) {
- __android_log_print(ANDROID_LOG_FATAL, "Qt A11y", "registerNatives failed");
- return -1;
- }
-
m_javaVM = vm;
return JNI_VERSION_1_4;
}
diff --git a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm
index 548c6a23f0..f89439734f 100644
--- a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm
+++ b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm
@@ -223,7 +223,14 @@ static void cleanupCocoaApplicationDelegate()
// events while the event loop is still running.
const QWindowList topLevels = QGuiApplication::topLevelWindows();
for (int i = 0; i < topLevels.size(); ++i) {
- QWindowSystemInterface::handleCloseEvent(topLevels.at(i));
+ QWindow *topLevelWindow = topLevels.at(i);
+ // Widgets have alreay received a CloseEvent from the QApplication
+ // QCloseEvent handler. (see canQuit above). Prevent running the
+ // CloseEvent logic twice, call close() directly.
+ if (topLevelWindow->inherits("QWidgetWindow"))
+ topLevelWindow->close();
+ else
+ QWindowSystemInterface::handleCloseEvent(topLevelWindow);
}
QWindowSystemInterface::flushWindowSystemEvents();
diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm
index 19753ccc89..fca7fa042c 100644
--- a/src/plugins/platforms/cocoa/qcocoaintegration.mm
+++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm
@@ -158,23 +158,42 @@ qreal QCocoaScreen::devicePixelRatio() const
QWindow *QCocoaScreen::topLevelAt(const QPoint &point) const
{
- // Get a z-ordered list of windows. Iterate through it until
- // we find a (Qt) window which contains the point.
- for (NSWindow *nsWindow in [NSApp orderedWindows]) {
- if (![nsWindow isKindOfClass:[QNSWindow class]])
+ NSPoint screenPoint = qt_mac_flipPoint(point);
+
+ // Search (hit test) for the top-level window. [NSWidow windowNumberAtPoint:
+ // belowWindowWithWindowNumber] may return windows that are not interesting
+ // to Qt. The search iterates until a suitable window or no window is found.
+ NSInteger topWindowNumber = 0;
+ QWindow *window = 0;
+ do {
+ // Get the top-most window, below any previously rejected window.
+ topWindowNumber = [NSWindow windowNumberAtPoint:screenPoint
+ belowWindowWithWindowNumber:topWindowNumber];
+
+ // Continue the search if the window does not belong to this process.
+ NSWindow *nsWindow = [NSApp windowWithWindowNumber:topWindowNumber];
+ if (nsWindow == 0)
continue;
- QNSWindow *qnsWindow = static_cast<QNSWindow *>(nsWindow);
- QCocoaWindow *cocoaWindow = qnsWindow.helper.platformWindow;
+
+ // Continue the search if the window does not belong to Qt.
+ if (![nsWindow conformsToProtocol:@protocol(QNSWindowProtocol)])
+ continue;
+
+ id<QNSWindowProtocol> proto = static_cast<id<QNSWindowProtocol> >(nsWindow);
+ QCocoaWindow *cocoaWindow = proto.helper.platformWindow;
if (!cocoaWindow)
continue;
- QWindow *window = cocoaWindow->window();
+ window = cocoaWindow->window();
+
+ // Continue the search if the window is not a top-level window.
if (!window->isTopLevel())
continue;
- if (window->geometry().contains(point))
- return window;
- }
- return QPlatformScreen::topLevelAt(point);
+ // Stop searching. The current window is the correct window.
+ break;
+ } while (topWindowNumber > 0);
+
+ return window;
}
extern CGContextRef qt_mac_cg_context(const QPaintDevice *pdev);
diff --git a/src/plugins/platforms/eglfs/qeglfswindow.h b/src/plugins/platforms/eglfs/qeglfswindow.h
index f3fd06037e..4403e3c28e 100644
--- a/src/plugins/platforms/eglfs/qeglfswindow.h
+++ b/src/plugins/platforms/eglfs/qeglfswindow.h
@@ -66,6 +66,8 @@ public:
void lower() Q_DECL_OVERRIDE;
void propagateSizeHints() Q_DECL_OVERRIDE { }
+ void setOpacity(qreal) Q_DECL_OVERRIDE { }
+ void setMask(const QRegion &) Q_DECL_OVERRIDE { }
bool setKeyboardGrabEnabled(bool) Q_DECL_OVERRIDE { return false; }
bool setMouseGrabEnabled(bool) Q_DECL_OVERRIDE { return false; }
diff --git a/src/plugins/platforms/ios/qiosinputcontext.mm b/src/plugins/platforms/ios/qiosinputcontext.mm
index 8be3846e06..d109d53168 100644
--- a/src/plugins/platforms/ios/qiosinputcontext.mm
+++ b/src/plugins/platforms/ios/qiosinputcontext.mm
@@ -54,7 +54,6 @@
QIOSInputContext *m_context;
BOOL m_keyboardVisible;
BOOL m_keyboardVisibleAndDocked;
- BOOL m_ignoreKeyboardChanges;
BOOL m_touchPressWhileKeyboardVisible;
BOOL m_keyboardHiddenByGesture;
QRectF m_keyboardRect;
@@ -74,7 +73,6 @@
m_context = context;
m_keyboardVisible = NO;
m_keyboardVisibleAndDocked = NO;
- m_ignoreKeyboardChanges = NO;
m_touchPressWhileKeyboardVisible = NO;
m_keyboardHiddenByGesture = NO;
m_duration = 0;
@@ -160,7 +158,7 @@
- (void) keyboardWillShow:(NSNotification *)notification
{
- if (m_ignoreKeyboardChanges)
+ if ([QUIView inUpdateKeyboardLayout])
return;
// Note that UIKeyboardWillShowNotification is only sendt when the keyboard is docked.
m_keyboardVisibleAndDocked = YES;
@@ -175,7 +173,7 @@
- (void) keyboardWillHide:(NSNotification *)notification
{
- if (m_ignoreKeyboardChanges)
+ if ([QUIView inUpdateKeyboardLayout])
return;
// Note that UIKeyboardWillHideNotification is also sendt when the keyboard is undocked.
m_keyboardVisibleAndDocked = NO;
@@ -407,11 +405,7 @@ void QIOSInputContext::update(Qt::InputMethodQueries query)
void QIOSInputContext::reset()
{
- // Since the call to reset will cause a 'keyboardWillHide'
- // notification to be sendt, we block keyboard nofifications to avoid artifacts:
- m_keyboardListener->m_ignoreKeyboardChanges = true;
[m_focusView reset];
- m_keyboardListener->m_ignoreKeyboardChanges = false;
}
void QIOSInputContext::commit()
diff --git a/src/plugins/platforms/ios/quiview.h b/src/plugins/platforms/ios/quiview.h
index 575dedab89..122e7c604b 100644
--- a/src/plugins/platforms/ios/quiview.h
+++ b/src/plugins/platforms/ios/quiview.h
@@ -75,4 +75,5 @@
- (void)updateInputMethodWithQuery:(Qt::InputMethodQueries)query;
- (void)reset;
- (void)commit;
++ (bool)inUpdateKeyboardLayout;
@end
diff --git a/src/plugins/platforms/ios/quiview_textinput.mm b/src/plugins/platforms/ios/quiview_textinput.mm
index 03006b3f99..e65ac1cc46 100644
--- a/src/plugins/platforms/ios/quiview_textinput.mm
+++ b/src/plugins/platforms/ios/quiview_textinput.mm
@@ -45,9 +45,12 @@ class StaticVariables
{
public:
QInputMethodQueryEvent inputMethodQueryEvent;
+ bool inUpdateKeyboardLayout;
QTextCharFormat markedTextFormat;
- StaticVariables() : inputMethodQueryEvent(Qt::ImQueryInput)
+ StaticVariables()
+ : inputMethodQueryEvent(Qt::ImQueryInput)
+ , inUpdateKeyboardLayout(false)
{
// There seems to be no way to query how the preedit text
// should be drawn. So we need to hard-code the color.
@@ -152,6 +155,47 @@ Q_GLOBAL_STATIC(StaticVariables, staticVariables);
return [super resignFirstResponder];
}
++ (bool)inUpdateKeyboardLayout
+{
+ return staticVariables()->inUpdateKeyboardLayout;
+}
+
+- (void)updateKeyboardLayout
+{
+ if (![self isFirstResponder])
+ return;
+
+ // There seems to be no API to inform that the keyboard layout needs to update.
+ // As a work-around, we quickly resign first responder just to reassign it again.
+ QScopedValueRollback<bool> rollback(staticVariables()->inUpdateKeyboardLayout);
+ staticVariables()->inUpdateKeyboardLayout = true;
+ [super resignFirstResponder];
+ [self updateTextInputTraits];
+ [super becomeFirstResponder];
+}
+
+- (void)updateUITextInputDelegate:(NSNumber *)intQuery
+{
+ // As documented, we should not report textWillChange/textDidChange unless the text
+ // was changed externally. That will cause spell checking etc to fail. But we don't
+ // really know if the text/selection was changed by UITextInput or Qt/app when getting
+ // update calls from Qt. We therefore use a less ideal approach where we always assume
+ // that UITextView caused the change if we're currently processing an event sendt from it.
+ if (m_inSendEventToFocusObject)
+ return;
+
+ Qt::InputMethodQueries query = Qt::InputMethodQueries([intQuery intValue]);
+ if (query & (Qt::ImCursorPosition | Qt::ImAnchorPosition)) {
+ [self.inputDelegate selectionWillChange:id<UITextInput>(self)];
+ [self.inputDelegate selectionDidChange:id<UITextInput>(self)];
+ }
+
+ if (query & Qt::ImSurroundingText) {
+ [self.inputDelegate textWillChange:id<UITextInput>(self)];
+ [self.inputDelegate textDidChange:id<UITextInput>(self)];
+ }
+}
+
- (void)updateInputMethodWithQuery:(Qt::InputMethodQueries)query
{
Q_UNUSED(query);
@@ -160,26 +204,13 @@ Q_GLOBAL_STATIC(StaticVariables, staticVariables);
if (!focusObject)
return;
- if (!m_inSendEventToFocusObject) {
- if (query & (Qt::ImCursorPosition | Qt::ImAnchorPosition))
- [self.inputDelegate selectionWillChange:id<UITextInput>(self)];
- if (query & Qt::ImSurroundingText)
- [self.inputDelegate textWillChange:id<UITextInput>(self)];
- }
-
// Note that we ignore \a query, and instead update using Qt::ImQueryInput. This enables us to just
// store the event without copying out the result from the event each time. Besides, we seem to be
// called with Qt::ImQueryInput when only changing selection, and always if typing text. So there would
// not be any performance gain by only updating \a query.
staticVariables()->inputMethodQueryEvent = QInputMethodQueryEvent(Qt::ImQueryInput);
QCoreApplication::sendEvent(focusObject, &staticVariables()->inputMethodQueryEvent);
-
- if (!m_inSendEventToFocusObject) {
- if (query & (Qt::ImCursorPosition | Qt::ImAnchorPosition))
- [self.inputDelegate selectionDidChange:id<UITextInput>(self)];
- if (query & Qt::ImSurroundingText)
- [self.inputDelegate textDidChange:id<UITextInput>(self)];
- }
+ [self updateUITextInputDelegate:[NSNumber numberWithInt:int(query)]];
}
- (void)sendEventToFocusObject:(QEvent &)e
@@ -189,35 +220,31 @@ Q_GLOBAL_STATIC(StaticVariables, staticVariables);
return;
// While sending the event, we will receive back updateInputMethodWithQuery calls.
- // To not confuse iOS, we cannot not call textWillChange/textDidChange at that
- // point since it will cause spell checking etc to fail. So we use a guard.
+ // Note that it would be more correct to post the event instead, but UITextInput expects
+ // callbacks to take effect immediately (it will query us for information after a callback).
+ QScopedValueRollback<BOOL> rollback(m_inSendEventToFocusObject);
m_inSendEventToFocusObject = YES;
QCoreApplication::sendEvent(focusObject, &e);
- m_inSendEventToFocusObject = NO;
}
- (void)reset
{
- [self.inputDelegate textWillChange:id<UITextInput>(self)];
[self setMarkedText:@"" selectedRange:NSMakeRange(0, 0)];
[self updateInputMethodWithQuery:Qt::ImQueryInput];
-
- if ([self isFirstResponder]) {
- // There seem to be no way to inform that the keyboard needs to update (since
- // text input traits might have changed). As a work-around, we quickly resign
- // first responder status just to reassign it again:
- [super resignFirstResponder];
- [self updateTextInputTraits];
- [super becomeFirstResponder];
- }
- [self.inputDelegate textDidChange:id<UITextInput>(self)];
+ // Guard agains recursive callbacks by posting calls to UITextInput
+ [self performSelectorOnMainThread:@selector(updateKeyboardLayout) withObject:nil waitUntilDone:NO];
+ [self performSelectorOnMainThread:@selector(updateUITextInputDelegate:)
+ withObject:[NSNumber numberWithInt:int(Qt::ImQueryInput)]
+ waitUntilDone:NO];
}
- (void)commit
{
- [self.inputDelegate textWillChange:id<UITextInput>(self)];
[self unmarkText];
- [self.inputDelegate textDidChange:id<UITextInput>(self)];
+ // Guard agains recursive callbacks by posting calls to UITextInput
+ [self performSelectorOnMainThread:@selector(updateUITextInputDelegate:)
+ withObject:[NSNumber numberWithInt:int(Qt::ImSurroundingText)]
+ waitUntilDone:NO];
}
- (QVariant)imValue:(Qt::InputMethodQuery)query
diff --git a/src/plugins/platforms/windows/accessible/iaccessible2.cpp b/src/plugins/platforms/windows/accessible/iaccessible2.cpp
index 7f2ed86404..d56925d0c4 100644
--- a/src/plugins/platforms/windows/accessible/iaccessible2.cpp
+++ b/src/plugins/platforms/windows/accessible/iaccessible2.cpp
@@ -522,6 +522,7 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_locale(IA2Locale *locale)
QLocale l;
res.country = QStringToBSTR(QLocale::countryToString(l.country()));
res.language = QStringToBSTR(QLocale::languageToString(l.language()));
+ res.variant = QStringToBSTR(QString());
*locale = res;
return S_OK;
}
diff --git a/src/plugins/platforms/windows/qwindowskeymapper.cpp b/src/plugins/platforms/windows/qwindowskeymapper.cpp
index 0b257cc48f..6bcfe01a18 100644
--- a/src/plugins/platforms/windows/qwindowskeymapper.cpp
+++ b/src/plugins/platforms/windows/qwindowskeymapper.cpp
@@ -893,6 +893,7 @@ bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, const MSG &ms
case Qt::Key_Plus:
case Qt::Key_Minus:
case Qt::Key_Period:
+ case Qt::Key_Comma:
case Qt::Key_0:
case Qt::Key_1:
case Qt::Key_2:
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp
index a46fe437d8..74d8b7c2c8 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
@@ -337,12 +337,38 @@ void QXcbWindow::create()
#endif //defined(XCB_USE_GLX) || defined(XCB_USE_EGL)
{
m_window = xcb_generate_id(xcb_connection());
+ m_visualId = m_screen->screen()->root_visual;
m_depth = m_screen->screen()->root_depth;
+
+ uint32_t mask = 0;
+ uint32_t values[3];
+
+ if (m_format.alphaBufferSize() == 8) {
+ xcb_depth_iterator_t depthIter = xcb_screen_allowed_depths_iterator(m_screen->screen());
+ while (depthIter.rem) {
+ if (depthIter.data->depth == 32) {
+ xcb_visualtype_iterator_t visualIter = xcb_depth_visuals_iterator(depthIter.data);
+ if (visualIter.rem) {
+ m_visualId = visualIter.data->visual_id;
+ m_depth = 32;
+ uint32_t colormap = xcb_generate_id(xcb_connection());
+ xcb_create_colormap(xcb_connection(), XCB_COLORMAP_ALLOC_NONE, colormap,
+ xcb_parent_id, m_visualId);
+ mask |= XCB_CW_BACK_PIXEL | XCB_CW_BORDER_PIXEL | XCB_CW_COLORMAP;
+ values[0] = m_screen->screen()->white_pixel;
+ values[1] = m_screen->screen()->black_pixel;
+ values[2] = colormap;
+ break;
+ }
+ }
+ xcb_depth_next(&depthIter);
+ }
+ }
+
m_imageFormat = imageFormatForDepth(m_depth);
- m_visualId = m_screen->screen()->root_visual;
Q_XCB_CALL(xcb_create_window(xcb_connection(),
- XCB_COPY_FROM_PARENT, // depth -- same as root
+ m_depth,
m_window, // window id
xcb_parent_id, // parent window id
rect.x(),
@@ -352,8 +378,8 @@ void QXcbWindow::create()
0, // border width
XCB_WINDOW_CLASS_INPUT_OUTPUT, // window class
m_visualId, // visual
- 0, // value mask
- 0)); // value list
+ mask,
+ values));
}
connection()->addWindowEventListener(m_window, this);