diff options
Diffstat (limited to 'src/plugins/platforms')
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoawindow.h | 1 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoawindow.mm | 8 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qnsview.mm | 45 | ||||
-rw-r--r-- | src/plugins/platforms/eglfs/qeglfshooks_stub.cpp | 2 | ||||
-rw-r--r-- | src/plugins/platforms/ios/qioseventdispatcher.mm | 9 | ||||
-rw-r--r-- | src/plugins/platforms/ios/qiosglobal.h | 2 | ||||
-rw-r--r-- | src/plugins/platforms/ios/qiosglobal.mm | 9 | ||||
-rw-r--r-- | src/plugins/platforms/ios/qiosinputcontext.h | 4 | ||||
-rw-r--r-- | src/plugins/platforms/ios/qiosinputcontext.mm | 172 | ||||
-rw-r--r-- | src/plugins/platforms/windows/qwindowsdialoghelpers.cpp | 13 |
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); |