summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/platforms')
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.h1
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.mm8
-rw-r--r--src/plugins/platforms/cocoa/qnsview.mm45
-rw-r--r--src/plugins/platforms/eglfs/qeglfshooks_stub.cpp2
-rw-r--r--src/plugins/platforms/ios/qioseventdispatcher.mm9
-rw-r--r--src/plugins/platforms/ios/qiosglobal.h2
-rw-r--r--src/plugins/platforms/ios/qiosglobal.mm9
-rw-r--r--src/plugins/platforms/ios/qiosinputcontext.h4
-rw-r--r--src/plugins/platforms/ios/qiosinputcontext.mm172
-rw-r--r--src/plugins/platforms/windows/qwindowsdialoghelpers.cpp13
10 files changed, 180 insertions, 85 deletions
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.h b/src/plugins/platforms/cocoa/qcocoawindow.h
index a43cf73d34..b232c7a4d3 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.h
+++ b/src/plugins/platforms/cocoa/qcocoawindow.h
@@ -268,6 +268,7 @@ public: // for QNSView
bool m_inConstructor;
bool m_inSetVisible;
+ bool m_inSetGeometry;
#ifndef QT_NO_OPENGL
QCocoaGLContext *m_glContext;
#endif
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm
index f536e20b39..6656212457 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.mm
+++ b/src/plugins/platforms/cocoa/qcocoawindow.mm
@@ -381,6 +381,7 @@ QCocoaWindow::QCocoaWindow(QWindow *tlw)
, m_windowUnderMouse(false)
, m_inConstructor(true)
, m_inSetVisible(false)
+ , m_inSetGeometry(false)
#ifndef QT_NO_OPENGL
, m_glContext(0)
#endif
@@ -470,6 +471,8 @@ QSurfaceFormat QCocoaWindow::format() const
void QCocoaWindow::setGeometry(const QRect &rectIn)
{
+ QBoolBlocker inSetGeometry(m_inSetGeometry, true);
+
QRect rect = rectIn;
// This means it is a call from QWindow::setFramePosition() and
// the coordinates include the frame (size is still the contents rectangle).
@@ -1754,6 +1757,11 @@ void QCocoaWindow::updateExposedGeometry()
if (!m_geometryUpdateExposeAllowed)
return;
+ // Do not send incorrect exposes in case the window is not even visible yet.
+ // We might get here as a result of a resize() from QWidget's show(), for instance.
+ if (!window()->isVisible())
+ return;
+
if (!isWindowExposable())
return;
diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm
index fa85a2bf54..699340795d 100644
--- a/src/plugins/platforms/cocoa/qnsview.mm
+++ b/src/plugins/platforms/cocoa/qnsview.mm
@@ -361,12 +361,11 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil;
// Send a geometry change event to Qt, if it's ready to handle events
if (!m_platformWindow->m_inConstructor) {
QWindowSystemInterface::handleGeometryChange(m_window, geometry);
- // Do not send incorrect exposes in case the window is not even visible yet.
- // We might get here as a result of a resize() from QWidget's show(), for instance.
- if (m_platformWindow->window()->isVisible()) {
- m_platformWindow->updateExposedGeometry();
+ m_platformWindow->updateExposedGeometry();
+ // Guard against processing window system events during QWindow::setGeometry
+ // calles, which Qt and Qt applications do not excpect.
+ if (!m_platformWindow->m_inSetGeometry)
QWindowSystemInterface::flushWindowSystemEvents();
- }
}
}
@@ -603,7 +602,8 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil;
{
if (m_window->flags() & Qt::WindowTransparentForInput)
return NO;
- QWindowSystemInterface::handleWindowActivated([self topLevelWindow]);
+ if (!m_platformWindow->windowIsPopupType())
+ QWindowSystemInterface::handleWindowActivated([self topLevelWindow]);
return YES;
}
@@ -662,6 +662,19 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil;
m_frameStrutButtons = Qt::NoButton;
}
+- (NSPoint) screenMousePoint:(NSEvent *)theEvent
+{
+ NSPoint screenPoint;
+ if (theEvent) {
+ NSPoint windowPoint = [theEvent locationInWindow];
+ NSRect screenRect = [[theEvent window] convertRectToScreen:NSMakeRect(windowPoint.x, windowPoint.y, 1, 1)];
+ screenPoint = screenRect.origin;
+ } else {
+ screenPoint = [NSEvent mouseLocation];
+ }
+ return screenPoint;
+}
+
- (void)handleMouseEvent:(NSEvent *)theEvent
{
[self handleTabletEvent: theEvent];
@@ -676,23 +689,7 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil;
m_platformWindow->m_forwardWindow = 0;
}
- NSPoint globalPos = [NSEvent mouseLocation];
-
- if ([self.window parentWindow]
- && (theEvent.type == NSLeftMouseDragged || theEvent.type == NSLeftMouseUp)) {
- // QToolBar can be implemented as a child window on top of its main window
- // (with a borderless NSWindow). If an option "unified toolbar" set on the main window,
- // it's possible to drag such a window using this toolbar.
- // While handling mouse drag events, QToolBar moves the window (QWidget::move).
- // In such a combination [NSEvent mouseLocation] is very different from the
- // real event location and as a result a window will move chaotically.
- NSPoint winPoint = [theEvent locationInWindow];
- NSRect tmpRect = NSMakeRect(winPoint.x, winPoint.y, 1., 1.);
- tmpRect = [[theEvent window] convertRectToScreen:tmpRect];
- globalPos = tmpRect.origin;
- }
-
- [targetView convertFromScreen:globalPos toWindowPoint:&qtWindowPoint andScreenPoint:&qtScreenPoint];
+ [targetView convertFromScreen:[self screenMousePoint:theEvent] toWindowPoint:&qtWindowPoint andScreenPoint:&qtScreenPoint];
ulong timestamp = [theEvent timestamp] * 1000;
QCocoaDrag* nativeDrag = QCocoaIntegration::instance()->drag();
@@ -865,7 +862,7 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil;
QPointF windowPoint;
QPointF screenPoint;
- [self convertFromScreen:[NSEvent mouseLocation] toWindowPoint:&windowPoint andScreenPoint:&screenPoint];
+ [self convertFromScreen:[self screenMousePoint:theEvent] toWindowPoint:&windowPoint andScreenPoint:&screenPoint];
QWindow *childWindow = m_platformWindow->childWindowAt(windowPoint.toPoint());
// Top-level windows generate enter-leave events for sub-windows.
diff --git a/src/plugins/platforms/eglfs/qeglfshooks_stub.cpp b/src/plugins/platforms/eglfs/qeglfshooks_stub.cpp
index b6b1be9244..26d77a2abb 100644
--- a/src/plugins/platforms/eglfs/qeglfshooks_stub.cpp
+++ b/src/plugins/platforms/eglfs/qeglfshooks_stub.cpp
@@ -63,11 +63,13 @@ QByteArray QEglFSHooks::fbDeviceName() const
int QEglFSHooks::framebufferIndex() const
{
int fbIndex = 0;
+#ifndef QT_NO_REGULAREXPRESSION
QRegularExpression fbIndexRx(QLatin1String("fb(\\d+)"));
QRegularExpressionMatch match = fbIndexRx.match(fbDeviceName());
if (match.hasMatch())
fbIndex = match.captured(1).toInt();
+#endif
return fbIndex;
}
diff --git a/src/plugins/platforms/ios/qioseventdispatcher.mm b/src/plugins/platforms/ios/qioseventdispatcher.mm
index 66fd9cd1e5..ffffc4cbc4 100644
--- a/src/plugins/platforms/ios/qioseventdispatcher.mm
+++ b/src/plugins/platforms/ios/qioseventdispatcher.mm
@@ -317,11 +317,16 @@ static bool rootLevelRunLoopIntegration()
}
#if defined(Q_PROCESSOR_X86)
-# define SET_STACK_POINTER "mov %0, %%esp"
# define FUNCTION_CALL_ALIGNMENT 16
+# if defined(Q_PROCESSOR_X86_32)
+# define SET_STACK_POINTER "mov %0, %%esp"
+# elif defined(Q_PROCESSOR_X86_64)
+# define SET_STACK_POINTER "movq %0, %%rsp"
+# endif
#elif defined(Q_PROCESSOR_ARM)
-# define SET_STACK_POINTER "mov sp, %0"
+# // Valid for both 32 and 64-bit ARM
# define FUNCTION_CALL_ALIGNMENT 4
+# define SET_STACK_POINTER "mov sp, %0"
#else
# error "Unknown processor family"
#endif
diff --git a/src/plugins/platforms/ios/qiosglobal.h b/src/plugins/platforms/ios/qiosglobal.h
index dbedba7e85..f7b9cd7015 100644
--- a/src/plugins/platforms/ios/qiosglobal.h
+++ b/src/plugins/platforms/ios/qiosglobal.h
@@ -62,7 +62,7 @@ QPointF fromCGPoint(const CGPoint &point);
Qt::ScreenOrientation toQtScreenOrientation(UIDeviceOrientation uiDeviceOrientation);
UIDeviceOrientation fromQtScreenOrientation(Qt::ScreenOrientation qtOrientation);
-QRect fromPortraitToPrimary(const QRect &rect, QPlatformScreen *screen);
+
int infoPlistValue(NSString* key, int defaultValue);
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/ios/qiosglobal.mm b/src/plugins/platforms/ios/qiosglobal.mm
index 71d5a58088..9f10c3e287 100644
--- a/src/plugins/platforms/ios/qiosglobal.mm
+++ b/src/plugins/platforms/ios/qiosglobal.mm
@@ -127,15 +127,6 @@ UIDeviceOrientation fromQtScreenOrientation(Qt::ScreenOrientation qtOrientation)
return uiOrientation;
}
-QRect fromPortraitToPrimary(const QRect &rect, QPlatformScreen *screen)
-{
- // UIScreen is always in portrait. Use this function to convert CGRects
- // aligned with UIScreen into whatever is the current orientation of QScreen.
- QRect geometry = screen->geometry();
- return geometry.width() < geometry.height() ? rect
- : QRect(rect.y(), geometry.height() - rect.width() - rect.x(), rect.height(), rect.width());
-}
-
int infoPlistValue(NSString* key, int defaultValue)
{
static NSBundle *bundle = [NSBundle mainBundle];
diff --git a/src/plugins/platforms/ios/qiosinputcontext.h b/src/plugins/platforms/ios/qiosinputcontext.h
index 5791367d84..1f1130f932 100644
--- a/src/plugins/platforms/ios/qiosinputcontext.h
+++ b/src/plugins/platforms/ios/qiosinputcontext.h
@@ -51,9 +51,10 @@ QT_BEGIN_NAMESPACE
struct ImeState
{
- ImeState() : currentState(0) {}
+ ImeState() : currentState(0), focusObject(0) {}
Qt::InputMethodQueries update(Qt::InputMethodQueries properties);
QInputMethodQueryEvent currentState;
+ QObject *focusObject;
};
class QIOSInputContext : public QPlatformInputContext
@@ -82,6 +83,7 @@ public:
void commit();
const ImeState &imeState() { return m_imeState; };
+ bool inputMethodAccepted() const;
bool isReloadingInputViewsFromUpdate() const { return m_isReloadingInputViewsFromUpdate; }
diff --git a/src/plugins/platforms/ios/qiosinputcontext.mm b/src/plugins/platforms/ios/qiosinputcontext.mm
index c038628fd9..072a49c7c5 100644
--- a/src/plugins/platforms/ios/qiosinputcontext.mm
+++ b/src/plugins/platforms/ios/qiosinputcontext.mm
@@ -46,25 +46,28 @@
#include "qiosglobal.h"
#include "qiosintegration.h"
#include "qiostextresponder.h"
+#include "qiosviewcontroller.h"
#include "qioswindow.h"
#include "quiview.h"
#include <QGuiApplication>
#include <QtGui/private/qwindow_p.h>
+// -------------------------------------------------------------------------
+
static QUIView *focusView()
{
return qApp->focusWindow() ?
reinterpret_cast<QUIView *>(qApp->focusWindow()->winId()) : 0;
}
-@interface QIOSKeyboardListener : UIGestureRecognizer {
+// -------------------------------------------------------------------------
+
+@interface QIOSKeyboardListener : UIGestureRecognizer <UIGestureRecognizerDelegate> {
@public
QIOSInputContext *m_context;
BOOL m_keyboardVisible;
BOOL m_keyboardVisibleAndDocked;
- BOOL m_touchPressWhileKeyboardVisible;
- BOOL m_keyboardHiddenByGesture;
QRectF m_keyboardRect;
CGRect m_keyboardEndRect;
NSTimeInterval m_duration;
@@ -77,13 +80,11 @@ static QUIView *focusView()
- (id)initWithQIOSInputContext:(QIOSInputContext *)context
{
- self = [super initWithTarget:self action:@selector(gestureTriggered)];
+ self = [super initWithTarget:self action:@selector(gestureStateChanged:)];
if (self) {
m_context = context;
m_keyboardVisible = NO;
m_keyboardVisibleAndDocked = NO;
- m_touchPressWhileKeyboardVisible = NO;
- m_keyboardHiddenByGesture = NO;
m_duration = 0;
m_curve = UIViewAnimationCurveEaseOut;
m_viewController = 0;
@@ -99,10 +100,9 @@ static QUIView *focusView()
Q_ASSERT(m_viewController);
// Attach 'hide keyboard' gesture to the window, but keep it disabled when the
- // keyboard is not visible. Note that we never trigger the gesture the way it is intended
- // since we don't want to cancel touch events and interrupt flicking etc. Instead we use
- // the gesture framework more as an event filter and hide the keyboard silently.
+ // keyboard is not visible.
self.enabled = NO;
+ self.cancelsTouchesInView = NO;
self.delaysTouchesEnded = NO;
[m_viewController.view.window addGestureRecognizer:self];
}
@@ -156,11 +156,19 @@ static QUIView *focusView()
// Note that UIKeyboardWillShowNotification is only sendt when the keyboard is docked.
m_keyboardVisibleAndDocked = YES;
m_keyboardEndRect = [[[notification userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
- self.enabled = YES;
+
if (!m_duration) {
m_duration = [[notification.userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
m_curve = UIViewAnimationCurve([[notification.userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] integerValue]);
}
+
+ UIResponder *firstResponder = [UIResponder currentFirstResponder];
+ if (![firstResponder isKindOfClass:[QIOSTextInputResponder class]])
+ return;
+
+ // Enable hide-keyboard gesture
+ self.enabled = YES;
+
m_context->scrollToCursor();
}
@@ -169,7 +177,7 @@ static QUIView *focusView()
// Note that UIKeyboardWillHideNotification is also sendt when the keyboard is undocked.
m_keyboardVisibleAndDocked = NO;
m_keyboardEndRect = [[[notification userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
- if (!m_keyboardHiddenByGesture) {
+ if (self.state != UIGestureRecognizerStateBegan) {
// Only disable the gesture if the hiding of the keyboard was not caused by it.
// Otherwise we need to await the final touchEnd callback for doing some clean-up.
self.enabled = NO;
@@ -202,54 +210,81 @@ static QUIView *focusView()
}
}
-- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
+// -------------------------------------------------------------------------
+
+- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
- CGPoint p = [[touches anyObject] locationInView:m_viewController.view.window];
- if (CGRectContainsPoint(m_keyboardEndRect, p)) {
- m_keyboardHiddenByGesture = YES;
+ [super touchesBegan:touches withEvent:event];
- UIResponder *firstResponder = [UIResponder currentFirstResponder];
- Q_ASSERT([firstResponder isKindOfClass:[QIOSTextInputResponder class]]);
- [firstResponder resignFirstResponder];
- }
+ Q_ASSERT(m_keyboardVisibleAndDocked);
- [super touchesMoved:touches withEvent:event];
+ if ([touches count] != 1)
+ self.state = UIGestureRecognizerStateFailed;
}
-- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
+- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
- Q_ASSERT(m_keyboardVisibleAndDocked);
- m_touchPressWhileKeyboardVisible = YES;
- [super touchesBegan:touches withEvent:event];
+ [super touchesMoved:touches withEvent:event];
+
+ if (self.state != UIGestureRecognizerStatePossible)
+ return;
+
+ CGPoint touchPoint = [[touches anyObject] locationInView:m_viewController.view.window];
+ if (CGRectContainsPoint(m_keyboardEndRect, touchPoint))
+ self.state = UIGestureRecognizerStateBegan;
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
- m_touchPressWhileKeyboardVisible = NO;
- [self performSelectorOnMainThread:@selector(touchesEndedPostDelivery) withObject:nil waitUntilDone:NO];
[super touchesEnded:touches withEvent:event];
+
+ [self touchesEndedOrCancelled];
}
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
- m_touchPressWhileKeyboardVisible = NO;
- [self performSelectorOnMainThread:@selector(touchesEndedPostDelivery) withObject:nil waitUntilDone:NO];
[super touchesCancelled:touches withEvent:event];
+
+ [self touchesEndedOrCancelled];
+}
+
+- (void)touchesEndedOrCancelled
+{
+ // Defer final state change until next runloop iteration, so that Qt
+ // has a chance to process the final touch events first, before we eg.
+ // scroll the view.
+ dispatch_async(dispatch_get_main_queue (), ^{
+ // iOS will transition from began to changed by itself
+ Q_ASSERT(self.state != UIGestureRecognizerStateBegan);
+
+ if (self.state == UIGestureRecognizerStateChanged)
+ self.state = UIGestureRecognizerStateEnded;
+ else
+ self.state = UIGestureRecognizerStateFailed;
+ });
}
-- (void)touchesEndedPostDelivery
+- (void)gestureStateChanged:(id)sender
{
- // Do some clean-up _after_ touchEnd has been delivered to QUIView
- m_keyboardHiddenByGesture = NO;
+ Q_UNUSED(sender);
+
+ if (self.state == UIGestureRecognizerStateBegan) {
+ qImDebug() << "hide keyboard gesture was triggered";
+ UIResponder *firstResponder = [UIResponder currentFirstResponder];
+ Q_ASSERT([firstResponder isKindOfClass:[QIOSTextInputResponder class]]);
+ [firstResponder resignFirstResponder];
+ }
+}
+
+- (void)reset
+{
+ [super reset];
+
if (!m_keyboardVisibleAndDocked) {
+ qImDebug() << "keyboard was hidden, disabling hide-keyboard gesture";
self.enabled = NO;
- if (qApp->focusObject()) {
- // UI Controls are told to gain focus on touch release. So when the 'hide keyboard' gesture
- // finishes, the final touch end can trigger a control to gain focus. This is in conflict with
- // the gesture, so we clear focus once more as a work-around.
- static_cast<QWindowPrivate *>(QObjectPrivate::get(qApp->focusWindow()))->clearFocusObject();
- }
} else {
+ qImDebug() << "gesture completed without triggering, scrolling view to cursor";
m_context->scrollToCursor();
}
}
@@ -265,8 +300,11 @@ Qt::InputMethodQueries ImeState::update(Qt::InputMethodQueries properties)
QInputMethodQueryEvent newState(properties);
- if (qApp && qApp->focusObject())
- QCoreApplication::sendEvent(qApp->focusObject(), &newState);
+ // Update the focus object that the new state is based on
+ focusObject = qApp ? qApp->focusObject() : 0;
+
+ if (focusObject)
+ QCoreApplication::sendEvent(focusObject, &newState);
Qt::InputMethodQueries updatedProperties;
for (uint i = 0; i < (sizeof(Qt::ImQueryAll) * CHAR_BIT); ++i) {
@@ -313,11 +351,23 @@ QRectF QIOSInputContext::keyboardRect() const
void QIOSInputContext::showInputPanel()
{
// No-op, keyboard controlled fully by platform based on focus
+ qImDebug() << "can't show virtual keyboard without a focus object, ignoring";
}
void QIOSInputContext::hideInputPanel()
{
- // No-op, keyboard controlled fully by platform based on focus
+ if (![m_textResponder isFirstResponder]) {
+ qImDebug() << "QIOSTextInputResponder is not first responder, ignoring";
+ return;
+ }
+
+ if (qGuiApp->focusObject() != m_imeState.focusObject) {
+ qImDebug() << "current focus object does not match IM state, likely hiding from focusOut event, so ignoring";
+ return;
+ }
+
+ qImDebug() << "hiding VKB as requested by QInputMethod::hide()";
+ [m_textResponder resignFirstResponder];
}
void QIOSInputContext::clearCurrentFocusObject()
@@ -353,10 +403,10 @@ void QIOSInputContext::scrollToCursor()
if (!isQtApplication())
return;
- if (m_keyboardListener->m_touchPressWhileKeyboardVisible) {
- // Don't scroll to the cursor if the user is touching the screen. This
- // interferes with selection and the 'hide keyboard' gesture. Instead
- // we update scrolling upon touchEnd.
+ if (m_keyboardListener.state == UIGestureRecognizerStatePossible && m_keyboardListener.numberOfTouches == 1) {
+ // Don't scroll to the cursor if the user is touching the screen and possibly
+ // trying to trigger the hide-keyboard gesture.
+ qImDebug() << "preventing scrolling to cursor as we're still waiting for a possible gesture";
return;
}
@@ -426,6 +476,18 @@ void QIOSInputContext::setFocusObject(QObject *focusObject)
{
Q_UNUSED(focusObject);
+ qImDebug() << "new focus object =" << focusObject;
+
+ if (m_keyboardListener.state == UIGestureRecognizerStateChanged) {
+ // A new focus object may be set as part of delivering touch events to
+ // application during the hide-keyboard gesture, but we don't want that
+ // to result in a new object getting focus and bringing the keyboard up
+ // again.
+ qImDebug() << "clearing focus object" << focusObject << "as hide-keyboard gesture is active";
+ clearCurrentFocusObject();
+ return;
+ }
+
reset();
if (m_keyboardListener->m_keyboardVisibleAndDocked)
@@ -436,6 +498,8 @@ void QIOSInputContext::focusWindowChanged(QWindow *focusWindow)
{
Q_UNUSED(focusWindow);
+ qImDebug() << "new focus window =" << focusWindow;
+
reset();
[m_keyboardListener handleKeyboardRectChanged];
@@ -486,6 +550,26 @@ void QIOSInputContext::update(Qt::InputMethodQueries updatedProperties)
}
}
+bool QIOSInputContext::inputMethodAccepted() const
+{
+ // The IM enablement state is based on the last call to update()
+ bool lastKnownImEnablementState = m_imeState.currentState.value(Qt::ImEnabled).toBool();
+
+#if !defined(QT_NO_DEBUG)
+ // QPlatformInputContext keeps a cached value of the current IM enablement state that is
+ // updated by QGuiApplication when the current focus object changes, or by QInputMethod's
+ // update() function. If the focus object changes, but the change is not propagated as
+ // a signal to QGuiApplication due to bugs in the widget/graphicsview/qml stack, we'll
+ // end up with a stale value for QPlatformInputContext::inputMethodAccepted(). To be on
+ // the safe side we always use our own cached value to decide if IM is enabled, and try
+ // to detect the case where the two values are out of sync.
+ if (lastKnownImEnablementState != QPlatformInputContext::inputMethodAccepted())
+ qWarning("QPlatformInputContext::inputMethodAccepted() does not match actual focus object IM enablement!");
+#endif
+
+ return lastKnownImEnablementState;
+}
+
/*!
Called by the input item to reset the input method state.
*/
diff --git a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp
index 4cbead44c5..f1f472b3e2 100644
--- a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp
+++ b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp
@@ -1224,16 +1224,21 @@ void QWindowsNativeFileDialogBase::setNameFilters(const QStringList &filters)
QScopedArrayPointer<WCHAR> buffer(new WCHAR[totalStringLength + 2 * size]);
QScopedArrayPointer<COMDLG_FILTERSPEC> comFilterSpec(new COMDLG_FILTERSPEC[size]);
- const QString matchesAll = QStringLiteral(" (*)");
WCHAR *ptr = buffer.data();
// Split filter specification as 'Texts (*.txt[;] *.doc)'
// into description and filters specification as '*.txt;*.doc'
for (int i = 0; i < size; ++i) {
- // Display glitch (CLSID only): 'All files (*)' shows up as 'All files (*) (*)'
+ // Display glitch (CLSID only): Any filter not filtering on suffix (such as
+ // '*', 'a.*') will be duplicated in combo: 'All files (*) (*)',
+ // 'AAA files (a.*) (a.*)'
QString description = specs[i].description;
- if (!m_hideFiltersDetails && description.endsWith(matchesAll))
- description.truncate(description.size() - matchesAll.size());
+ const QString &filter = specs[i].filter;
+ if (!m_hideFiltersDetails && !filter.startsWith(QLatin1String("*."))) {
+ const int pos = description.lastIndexOf(QLatin1Char('('));
+ if (pos > 0)
+ description.truncate(pos);
+ }
// Add to buffer.
comFilterSpec[i].pszName = ptr;
ptr += description.toWCharArray(ptr);