summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/platforms')
-rw-r--r--src/plugins/platforms/cocoa/qcocoaaccessibility.h1
-rw-r--r--src/plugins/platforms/cocoa/qcocoaaccessibility.mm17
-rw-r--r--src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm3
-rw-r--r--src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm2
-rw-r--r--src/plugins/platforms/cocoa/qcocoadrag.mm2
-rw-r--r--src/plugins/platforms/cocoa/qcocoaprintdevice.mm3
-rwxr-xr-xsrc/plugins/platforms/cocoa/qcocoasystemtrayicon.mm96
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.mm11
-rw-r--r--src/plugins/platforms/cocoa/qmacclipboard.h17
-rw-r--r--src/plugins/platforms/cocoa/qmacclipboard.mm56
-rw-r--r--src/plugins/platforms/cocoa/qnsview.mm59
-rw-r--r--src/plugins/platforms/cocoa/qprintengine_mac.mm47
-rw-r--r--src/plugins/platforms/ios/qioseventdispatcher.mm10
-rw-r--r--src/plugins/platforms/ios/quiaccessibilityelement.mm3
-rw-r--r--src/plugins/platforms/windows/qwindowscursor.cpp12
-rw-r--r--src/plugins/platforms/windows/qwindowscursor.h2
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.cpp9
-rw-r--r--src/plugins/platforms/xcb/qxcbkeyboard.cpp12
18 files changed, 286 insertions, 76 deletions
diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibility.h b/src/plugins/platforms/cocoa/qcocoaaccessibility.h
index 96dbd23695..3d1c95a0b4 100644
--- a/src/plugins/platforms/cocoa/qcocoaaccessibility.h
+++ b/src/plugins/platforms/cocoa/qcocoaaccessibility.h
@@ -70,6 +70,7 @@ namespace QCocoaAccessible {
*/
NSString *macRole(QAccessibleInterface *interface);
+NSString *macSubrole(QAccessibleInterface *interface);
bool shouldBeIgnored(QAccessibleInterface *interface);
NSArray *unignoredChildren(QAccessibleInterface *interface);
NSString *getTranslatedAction(const QString &qtAction);
diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibility.mm b/src/plugins/platforms/cocoa/qcocoaaccessibility.mm
index 1ade985b79..00baeddb39 100644
--- a/src/plugins/platforms/cocoa/qcocoaaccessibility.mm
+++ b/src/plugins/platforms/cocoa/qcocoaaccessibility.mm
@@ -162,7 +162,7 @@ static void populateRoleMap()
}
/*
- Returns a Mac accessibility role for the given interface, or
+ Returns a Cocoa accessibility role for the given interface, or
NSAccessibilityUnknownRole if no role mapping is found.
*/
NSString *macRole(QAccessibleInterface *interface)
@@ -190,13 +190,24 @@ NSString *macRole(QAccessibleInterface *interface)
}
/*
- Mac accessibility supports ignoring elements, which means that
+ Returns a Cocoa sub role for the given interface.
+*/
+NSString *macSubrole(QAccessibleInterface *interface)
+{
+ QAccessible::State s = interface->state();
+ if (s.searchEdit)
+ return NSAccessibilitySearchFieldSubrole;
+ return nil;
+}
+
+/*
+ Cocoa accessibility supports ignoring elements, which means that
the elements are still present in the accessibility tree but is
not used by the screen reader.
*/
bool shouldBeIgnored(QAccessibleInterface *interface)
{
- // Mac accessibility does not have an attribute that corresponds to the Invisible/Offscreen
+ // Cocoa accessibility does not have an attribute that corresponds to the Invisible/Offscreen
// state. Ignore interfaces with those flags set.
const QAccessible::State state = interface->state();
if (state.invisible ||
diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm
index 9f803e411d..dd76852b62 100644
--- a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm
+++ b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm
@@ -135,6 +135,7 @@
defaultAttributes = [[NSArray alloc] initWithObjects:
NSAccessibilityRoleAttribute,
NSAccessibilityRoleDescriptionAttribute,
+ NSAccessibilitySubroleAttribute,
NSAccessibilityChildrenAttribute,
NSAccessibilityFocusedAttribute,
NSAccessibilityParentAttribute,
@@ -221,6 +222,8 @@
if ([attribute isEqualToString:NSAccessibilityRoleAttribute]) {
return role;
+ } else if ([attribute isEqualToString:NSAccessibilitySubroleAttribute]) {
+ return QCocoaAccessible::macSubrole(iface);
} else if ([attribute isEqualToString:NSAccessibilityRoleDescriptionAttribute]) {
return NSAccessibilityRoleDescription(role, nil);
} else if ([attribute isEqualToString:NSAccessibilityChildrenAttribute]) {
diff --git a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm
index 326628a261..9f7609f24c 100644
--- a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm
+++ b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm
@@ -396,7 +396,7 @@ static void cleanupCocoaApplicationDelegate()
*/
QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationActive, true /*forcePropagate*/);
- return NO;
+ return YES;
}
- (void)setReflectionDelegate:(NSObject <NSApplicationDelegate> *)oldDelegate
diff --git a/src/plugins/platforms/cocoa/qcocoadrag.mm b/src/plugins/platforms/cocoa/qcocoadrag.mm
index 2c8d391d2b..47b52c9fdd 100644
--- a/src/plugins/platforms/cocoa/qcocoadrag.mm
+++ b/src/plugins/platforms/cocoa/qcocoadrag.mm
@@ -132,7 +132,7 @@ Qt::DropAction QCocoaDrag::drag(QDrag *o)
QMacPasteboard dragBoard((CFStringRef) NSDragPboard, QMacInternalPasteboardMime::MIME_DND);
m_drag->mimeData()->setData(QLatin1String("application/x-qt-mime-type-name"), QByteArray("dummy"));
- dragBoard.setMimeData(m_drag->mimeData());
+ dragBoard.setMimeData(m_drag->mimeData(), QMacPasteboard::LazyRequest);
NSPoint event_location = [m_lastEvent locationInWindow];
NSPoint local_point = [m_lastView convertPoint:event_location fromView:nil];
diff --git a/src/plugins/platforms/cocoa/qcocoaprintdevice.mm b/src/plugins/platforms/cocoa/qcocoaprintdevice.mm
index 7322025df6..2101b68769 100644
--- a/src/plugins/platforms/cocoa/qcocoaprintdevice.mm
+++ b/src/plugins/platforms/cocoa/qcocoaprintdevice.mm
@@ -391,6 +391,9 @@ void QCocoaPrintDevice::loadDuplexModes() const
// If still no result, or not added in PPD, then add None
if (m_duplexModes.size() == 0 || !m_duplexModes.contains(QPrint::DuplexNone))
m_duplexModes.append(QPrint::DuplexNone);
+ // If have both modes, then can support DuplexAuto
+ if (m_duplexModes.contains(QPrint::DuplexLongSide) && m_duplexModes.contains(QPrint::DuplexShortSide))
+ m_duplexModes.append(QPrint::DuplexAuto);
m_haveDuplexModes = true;
}
diff --git a/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm b/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm
index 83c960d931..e449fd37d6 100755
--- a/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm
+++ b/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm
@@ -187,6 +187,14 @@ void QCocoaSystemTrayIcon::cleanup()
m_sys = 0;
}
+static bool heightCompareFunction (QSize a, QSize b) { return (a.height() < b.height()); }
+static QList<QSize> sortByHeight(const QList<QSize> sizes)
+{
+ QList<QSize> sorted = sizes;
+ std::sort(sorted.begin(), sorted.end(), heightCompareFunction);
+ return sorted;
+}
+
void QCocoaSystemTrayIcon::updateIcon(const QIcon &icon)
{
if (!m_sys)
@@ -196,16 +204,62 @@ void QCocoaSystemTrayIcon::updateIcon(const QIcon &icon)
const bool menuVisible = m_sys->item->menu && m_sys->item->menuVisible;
- CGFloat hgt = [[[NSApplication sharedApplication] mainMenu] menuBarHeight];
- const short scale = hgt - 4;
+ // The reccomended maximum title bar icon height is 18 points
+ // (device independent pixels). The menu height on past and
+ // current OS X versions is 22 points. Provide some future-proofing
+ // by deriving the icon height from the menu height.
+ const int padding = 4;
+ const int menuHeight = [[[NSApplication sharedApplication] mainMenu] menuBarHeight];
+ const int maxImageHeight = menuHeight - padding;
+
+ // Select pixmap based on the device pixel height. Ideally we would use
+ // the devicePixelRatio of the target screen, but that value is not
+ // known until draw time. Use qApp->devicePixelRatio, which returns the
+ // devicePixelRatio for the "best" screen on the system.
+ qreal devicePixelRatio = qApp->devicePixelRatio();
+ const int maxPixmapHeight = maxImageHeight * devicePixelRatio;
+ const QIcon::Mode mode = menuVisible ? QIcon::Selected : QIcon::Normal;
+ QSize selectedSize;
+ Q_FOREACH (const QSize& size, sortByHeight(icon.availableSizes(mode))) {
+ // Select a pixmap based on the height. We want the largest pixmap
+ // with a height smaller or equal to maxPixmapHeight. The pixmap
+ // may rectangular; assume it has a reasonable size. If there is
+ // not suitable pixmap use the smallest one the icon can provide.
+ if (size.height() <= maxPixmapHeight) {
+ selectedSize = size;
+ } else {
+ if (!selectedSize.isValid())
+ selectedSize = size;
+ break;
+ }
+ }
- QPixmap pm = m_sys->item->icon.pixmap(QSize(scale, scale),
- menuVisible ? QIcon::Selected : QIcon::Normal);
- if (pm.isNull()) {
- pm = QPixmap(scale, scale);
- pm.fill(Qt::transparent);
+ QPixmap pixmap = icon.pixmap(selectedSize, mode);
+
+ // Draw a low-resolution icon if there is not enough pixels for a retina
+ // icon. This prevents showing a small icon on retina displays.
+ if (devicePixelRatio > 1.0 && selectedSize.height() < maxPixmapHeight / 2)
+ devicePixelRatio = 1.0;
+
+ // Scale large pixmaps to fit the available menu bar area.
+ if (pixmap.height() > maxPixmapHeight)
+ pixmap = pixmap.scaledToHeight(maxPixmapHeight, Qt::SmoothTransformation);
+
+ // The icon will be stretched over the full height of the menu bar
+ // therefore we create a second pixmap which has the full height
+ QSize fullHeightSize(!pixmap.isNull() ? pixmap.width():
+ menuHeight * devicePixelRatio,
+ menuHeight * devicePixelRatio);
+ QPixmap fullHeightPixmap(fullHeightSize);
+ fullHeightPixmap.fill(Qt::transparent);
+ if (!pixmap.isNull()) {
+ QPainter p(&fullHeightPixmap);
+ QRect r = pixmap.rect();
+ r.moveCenter(fullHeightPixmap.rect().center());
+ p.drawPixmap(r, pixmap);
}
- NSImage *nsimage = static_cast<NSImage *>(qt_mac_create_nsimage(pm));
+
+ NSImage *nsimage = static_cast<NSImage *>(qt_mac_create_nsimage(fullHeightPixmap));
[(NSImageView*)[[m_sys->item item] view] setImage: nsimage];
[nsimage release];
}
@@ -327,18 +381,7 @@ QT_END_NAMESPACE
Q_UNUSED(notification);
down = NO;
- CGFloat hgt = [[[NSApplication sharedApplication] mainMenu] menuBarHeight];
- const short scale = hgt - 4;
-
- QPixmap pm = parent->icon.pixmap(QSize(scale, scale), QIcon::Normal);
- if (pm.isNull()) {
- pm = QPixmap(scale, scale);
- pm.fill(Qt::transparent);
- }
- NSImage *nsaltimage = static_cast<NSImage *>(qt_mac_create_nsimage(pm));
- [self setImage: nsaltimage];
- [nsaltimage release];
-
+ parent->systray->updateIcon(parent->icon);
parent->menuVisible = false;
[self setNeedsDisplay:YES];
@@ -350,18 +393,7 @@ QT_END_NAMESPACE
int clickCount = [mouseEvent clickCount];
[self setNeedsDisplay:YES];
- CGFloat hgt = [[[NSApplication sharedApplication] mainMenu] menuBarHeight];
- const short scale = hgt - 4;
-
- QPixmap pm = parent->icon.pixmap(QSize(scale, scale),
- parent->menuVisible ? QIcon::Selected : QIcon::Normal);
- if (pm.isNull()) {
- pm = QPixmap(scale, scale);
- pm.fill(Qt::transparent);
- }
- NSImage *nsaltimage = static_cast<NSImage *>(qt_mac_create_nsimage(pm));
- [self setImage: nsaltimage];
- [nsaltimage release];
+ parent->systray->updateIcon(parent->icon);
if (clickCount == 2) {
[self menuTrackingDone:nil];
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm
index 9259c2c772..3366e5bc3c 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.mm
+++ b/src/plugins/platforms/cocoa/qcocoawindow.mm
@@ -699,7 +699,7 @@ void QCocoaWindow::setVisible(bool visible)
exposeWindow();
if (m_nsWindow) {
- QWindowSystemInterface::flushWindowSystemEvents();
+ QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ExcludeUserInputEvents);
// setWindowState might have been called while the window was hidden and
// will not change the NSWindow state in that case. Sync up here:
@@ -1009,9 +1009,12 @@ void QCocoaWindow::raise()
[parentNSWindow addChildWindow:m_nsWindow ordered:NSWindowAbove];
} else {
[m_nsWindow orderFront: m_nsWindow];
- ProcessSerialNumber psn;
- GetCurrentProcess(&psn);
- SetFrontProcessWithOptions(&psn, kSetFrontProcessFrontWindowOnly);
+ static bool raiseProcess = qt_mac_resolveOption(true, "QT_MAC_SET_RAISE_PROCESS");
+ if (raiseProcess) {
+ ProcessSerialNumber psn;
+ GetCurrentProcess(&psn);
+ SetFrontProcessWithOptions(&psn, kSetFrontProcessFrontWindowOnly);
+ }
}
}
}
diff --git a/src/plugins/platforms/cocoa/qmacclipboard.h b/src/plugins/platforms/cocoa/qmacclipboard.h
index ba7a2e1aac..c5b6224545 100644
--- a/src/plugins/platforms/cocoa/qmacclipboard.h
+++ b/src/plugins/platforms/cocoa/qmacclipboard.h
@@ -43,15 +43,25 @@
QT_BEGIN_NAMESPACE
+class QMacMimeData;
class QMacPasteboard
{
+public:
+ enum DataRequestType { EagerRequest, LazyRequest };
+private:
struct Promise {
Promise() : itemId(0), convertor(0) { }
- Promise(int itemId, QMacInternalPasteboardMime *c, QString m, QVariant d, int o=0) : itemId(itemId), offset(o), convertor(c), mime(m), data(d) { }
+
+ static Promise eagerPromise(int itemId, QMacInternalPasteboardMime *c, QString m, QMacMimeData *d, int o = 0);
+ static Promise lazyPromise(int itemId, QMacInternalPasteboardMime *c, QString m, QMacMimeData *d, int o = 0);
+ Promise(int itemId, QMacInternalPasteboardMime *c, QString m, QMacMimeData *md, int o, DataRequestType drt);
+
int itemId, offset;
QMacInternalPasteboardMime *convertor;
QString mime;
- QVariant data;
+ QPointer<QMacMimeData> mimeData;
+ QVariant variantData;
+ DataRequestType dataRequestType;
};
QList<Promise> promises;
@@ -72,7 +82,8 @@ public:
PasteboardRef pasteBoard() const;
QMimeData *mimeData() const;
- void setMimeData(QMimeData *mime);
+
+ void setMimeData(QMimeData *mime, DataRequestType dataRequestType = EagerRequest);
QStringList formats() const;
bool hasFormat(const QString &format) const;
diff --git a/src/plugins/platforms/cocoa/qmacclipboard.mm b/src/plugins/platforms/cocoa/qmacclipboard.mm
index 65665ef790..b235625921 100644
--- a/src/plugins/platforms/cocoa/qmacclipboard.mm
+++ b/src/plugins/platforms/cocoa/qmacclipboard.mm
@@ -64,6 +64,26 @@ QT_BEGIN_NAMESPACE
QMacPasteboard code
*****************************************************************************/
+class QMacMimeData : public QMimeData
+{
+public:
+ QVariant variantData(const QString &mime) { return retrieveData(mime, QVariant::Invalid); }
+private:
+ QMacMimeData();
+};
+
+QMacPasteboard::Promise::Promise(int itemId, QMacInternalPasteboardMime *c, QString m, QMacMimeData *md, int o, DataRequestType drt)
+ : itemId(itemId), offset(o), convertor(c), mime(m), dataRequestType(drt)
+{
+ // Request the data from the application immediately for eager requests.
+ if (dataRequestType == QMacPasteboard::EagerRequest) {
+ variantData = md->variantData(m);
+ mimeData = 0;
+ } else {
+ mimeData = md;
+ }
+}
+
QMacPasteboard::QMacPasteboard(PasteboardRef p, uchar mt)
{
mac_mime_source = false;
@@ -103,6 +123,11 @@ QMacPasteboard::~QMacPasteboard()
// commit all promises for paste after exit close
for (int i = 0; i < promises.count(); ++i) {
const Promise &promise = promises.at(i);
+ // At this point app teardown has started and control is somewhere in the Q[Core]Application
+ // destructor. Skip "lazy" promises where the application has not provided data;
+ // the application will generally not be in a state to provide it.
+ if (promise.dataRequestType == LazyRequest)
+ continue;
QCFString flavor = QCFString(promise.convertor->flavorFor(promise.mime));
NSInteger pbItemId = promise.itemId;
promiseKeeper(paste, reinterpret_cast<PasteboardItemID>(pbItemId), flavor, this);
@@ -155,7 +180,17 @@ OSStatus QMacPasteboard::promiseKeeper(PasteboardRef paste, PasteboardItemID id,
qPrintable(flavorAsQString), qPrintable(promise.convertor->convertorName()), promise.offset);
#endif
- QList<QByteArray> md = promise.convertor->convertFromMime(promise.mime, promise.data, flavorAsQString);
+ // Get the promise data. If this is a "lazy" promise call variantData()
+ // to request the data from the application.
+ QVariant promiseData;
+ if (promise.dataRequestType == LazyRequest) {
+ if (!promise.mimeData.isNull())
+ promiseData = promise.mimeData->variantData(promise.mime);
+ } else {
+ promiseData = promise.variantData;
+ }
+
+ QList<QByteArray> md = promise.convertor->convertFromMime(promise.mime, promiseData, flavorAsQString);
if (md.size() <= promise.offset)
return cantGetFlavorErr;
const QByteArray &ba = md[promise.offset];
@@ -266,16 +301,8 @@ QMimeData
return mime;
}
-class QMacMimeData : public QMimeData
-{
-public:
- QVariant variantData(const QString &mime) { return retrieveData(mime, QVariant::Invalid); }
-private:
- QMacMimeData();
-};
-
void
-QMacPasteboard::setMimeData(QMimeData *mime_src)
+QMacPasteboard::setMimeData(QMimeData *mime_src, DataRequestType dataRequestType)
{
if (!paste)
return;
@@ -312,12 +339,17 @@ QMacPasteboard::setMimeData(QMimeData *mime_src)
continue;
QString flavor(c->flavorFor(mimeType));
if (!flavor.isEmpty()) {
- QVariant mimeData = static_cast<QMacMimeData*>(mime_src)->variantData(mimeType);
+ QMacMimeData *mimeData = static_cast<QMacMimeData*>(mime_src);
int numItems = c->count(mime_src);
for (int item = 0; item < numItems; ++item) {
const NSInteger itemID = item+1; //id starts at 1
- promises.append(QMacPasteboard::Promise(itemID, c, mimeType, mimeData, item));
+ //QMacPasteboard::Promise promise = (dataRequestType == QMacPasteboard::EagerRequest) ?
+ // QMacPasteboard::Promise::eagerPromise(itemID, c, mimeType, mimeData, item) :
+ // QMacPasteboard::Promise::lazyPromise(itemID, c, mimeType, mimeData, item);
+
+ QMacPasteboard::Promise promise(itemID, c, mimeType, mimeData, item, dataRequestType);
+ promises.append(promise);
PasteboardPutItemFlavor(paste, reinterpret_cast<PasteboardItemID>(itemID), QCFString(flavor), 0, kPasteboardFlavorNoFlags);
#ifdef DEBUG_PASTEBOARD
qDebug(" - adding %d %s [%s] <%s> [%d]",
diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm
index 06680228bc..ca98f6cec3 100644
--- a/src/plugins/platforms/cocoa/qnsview.mm
+++ b/src/plugins/platforms/cocoa/qnsview.mm
@@ -361,8 +361,12 @@ 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);
- m_platformWindow->updateExposedGeometry();
- QWindowSystemInterface::flushWindowSystemEvents();
+ // 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();
+ QWindowSystemInterface::flushWindowSystemEvents();
+ }
}
}
@@ -420,10 +424,12 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil;
#pragma clang diagnostic ignored "-Wobjc-method-access"
enum { NSWindowOcclusionStateVisible = 1UL << 1 };
#endif
+ // Older versions managed in -[QNSView viewDidMoveToWindow].
+ // Support QWidgetAction in NSMenu. Mavericks only sends this notification.
+ // Ideally we should support this in Qt as well, in order to disable animations
+ // when the window is occluded.
if ((NSUInteger)[self.window occlusionState] & NSWindowOcclusionStateVisible)
m_platformWindow->exposeWindow();
- else
- m_platformWindow->obscureWindow();
#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_9
#pragma clang diagnostic pop
#endif
@@ -686,7 +692,23 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil;
m_platformWindow->m_forwardWindow = 0;
}
- [targetView convertFromScreen:[NSEvent mouseLocation] toWindowPoint:&qtWindowPoint andScreenPoint:&qtScreenPoint];
+ 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];
ulong timestamp = [theEvent timestamp] * 1000;
QCocoaDrag* nativeDrag = QCocoaIntegration::instance()->drag();
@@ -699,6 +721,10 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil;
- (void)handleFrameStrutMouseEvent:(NSEvent *)theEvent
{
// get m_buttons in sync
+ // Don't send frme strut events if we are in the middle of a mouse drag.
+ if (m_buttons != Qt::NoButton)
+ return;
+
NSEventType ty = [theEvent type];
switch (ty) {
case NSLeftMouseDown:
@@ -710,6 +736,12 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil;
case NSRightMouseDown:
m_frameStrutButtons |= Qt::RightButton;
break;
+ case NSLeftMouseDragged:
+ m_frameStrutButtons |= Qt::LeftButton;
+ break;
+ case NSRightMouseDragged:
+ m_frameStrutButtons |= Qt::RightButton;
+ break;
case NSRightMouseUp:
m_frameStrutButtons &= ~Qt::RightButton;
break;
@@ -1337,10 +1369,6 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent)
}
QWindowSystemInterface::handleWheelEvent(m_window, qt_timestamp, qt_windowPoint, qt_screenPoint, pixelDelta, angleDelta, currentWheelModifiers, ph);
-
- if (momentumPhase == NSEventPhaseEnded || momentumPhase == NSEventPhaseCancelled || momentumPhase == NSEventPhaseNone) {
- currentWheelModifiers = Qt::NoModifier;
- }
} else
#endif
{
@@ -1806,6 +1834,19 @@ static QPoint mapWindowCoordinates(QWindow *source, QWindow *target, QPoint poin
return NO;
}
+- (BOOL)wantsPeriodicDraggingUpdates
+{
+ // From the documentation:
+ //
+ // "If the destination returns NO, these messages are sent only when the mouse moves
+ // or a modifier flag changes. Otherwise the destination gets the default behavior,
+ // where it receives periodic dragging-updated messages even if nothing changes."
+ //
+ // We do not want these constant drag update events while mouse is stationary,
+ // since we do all animations (autoscroll) with timers.
+ return NO;
+}
+
- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
{
return [self handleDrag : sender];
diff --git a/src/plugins/platforms/cocoa/qprintengine_mac.mm b/src/plugins/platforms/cocoa/qprintengine_mac.mm
index fb968f31e9..f684fef233 100644
--- a/src/plugins/platforms/cocoa/qprintengine_mac.mm
+++ b/src/plugins/platforms/cocoa/qprintengine_mac.mm
@@ -457,9 +457,6 @@ void QMacPrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &va
break;
case PPK_CustomBase:
break;
- case PPK_Duplex:
- // TODO Add support using PMSetDuplex / PMGetDuplex
- break;
case PPK_FontEmbedding:
break;
case PPK_PageOrder:
@@ -503,6 +500,29 @@ void QMacPrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &va
case PPK_DocumentName:
PMPrintSettingsSetJobName(d->settings(), QCFString(value.toString()));
break;
+ case PPK_Duplex: {
+ QPrint::DuplexMode mode = QPrint::DuplexMode(value.toInt());
+ if (mode == property(PPK_Duplex).toInt() || !d->m_printDevice->supportedDuplexModes().contains(mode))
+ break;
+ switch (mode) {
+ case QPrinter::DuplexNone:
+ PMSetDuplex(d->settings(), kPMDuplexNone);
+ break;
+ case QPrinter::DuplexAuto:
+ PMSetDuplex(d->settings(), d->m_pageLayout.orientation() == QPageLayout::Landscape ? kPMDuplexTumble : kPMDuplexNoTumble);
+ break;
+ case QPrinter::DuplexLongSide:
+ PMSetDuplex(d->settings(), kPMDuplexNoTumble);
+ break;
+ case QPrinter::DuplexShortSide:
+ PMSetDuplex(d->settings(), kPMDuplexTumble);
+ break;
+ default:
+ // Don't change
+ break;
+ }
+ break;
+ }
case PPK_FullPage:
if (value.toBool())
d->m_pageLayout.setMode(QPageLayout::FullPageMode);
@@ -602,10 +622,6 @@ QVariant QMacPrintEngine::property(PrintEnginePropertyKey key) const
case PPK_CustomBase:
// Special case, leave null
break;
- case PPK_Duplex:
- // TODO Add support using PMSetDuplex / PMGetDuplex
- ret = QPrinter::DuplexNone;
- break;
case PPK_FontEmbedding:
ret = false;
break;
@@ -647,6 +663,23 @@ QVariant QMacPrintEngine::property(PrintEnginePropertyKey key) const
ret = QCFString::toQString(name);
break;
}
+ case PPK_Duplex: {
+ PMDuplexMode mode = kPMDuplexNone;
+ PMGetDuplex(d->settings(), &mode);
+ switch (mode) {
+ case kPMDuplexNoTumble:
+ ret = QPrinter::DuplexLongSide;
+ break;
+ case kPMDuplexTumble:
+ ret = QPrinter::DuplexShortSide;
+ break;
+ case kPMDuplexNone:
+ default:
+ ret = QPrinter::DuplexNone;
+ break;
+ }
+ break;
+ }
case PPK_FullPage:
ret = d->m_pageLayout.mode() == QPageLayout::FullPageMode;
break;
diff --git a/src/plugins/platforms/ios/qioseventdispatcher.mm b/src/plugins/platforms/ios/qioseventdispatcher.mm
index 821599d113..ce7dfe2606 100644
--- a/src/plugins/platforms/ios/qioseventdispatcher.mm
+++ b/src/plugins/platforms/ios/qioseventdispatcher.mm
@@ -259,10 +259,16 @@ static void __attribute__((noinline, noreturn)) user_main_trampoline()
NSArray *arguments = [[NSProcessInfo processInfo] arguments];
int argc = arguments.count;
char **argv = new char*[argc];
+
for (int i = 0; i < argc; ++i) {
NSString *arg = [arguments objectAtIndex:i];
- argv[i] = reinterpret_cast<char *>(malloc([arg lengthOfBytesUsingEncoding:[NSString defaultCStringEncoding]]));
- strcpy(argv[i], [arg cStringUsingEncoding:[NSString defaultCStringEncoding]]);
+
+ NSStringEncoding cStringEncoding = [NSString defaultCStringEncoding];
+ unsigned int bufferSize = [arg lengthOfBytesUsingEncoding:cStringEncoding] + 1;
+ argv[i] = reinterpret_cast<char *>(malloc(bufferSize));
+
+ if (![arg getCString:argv[i] maxLength:bufferSize encoding:cStringEncoding])
+ qFatal("Could not convert argv[%d] to C string", i);
}
int exitCode = qtmn(argc, argv);
diff --git a/src/plugins/platforms/ios/quiaccessibilityelement.mm b/src/plugins/platforms/ios/quiaccessibilityelement.mm
index 331c38460c..63b6827ad3 100644
--- a/src/plugins/platforms/ios/quiaccessibilityelement.mm
+++ b/src/plugins/platforms/ios/quiaccessibilityelement.mm
@@ -152,6 +152,9 @@
if (state.disabled)
traits |= UIAccessibilityTraitNotEnabled;
+ if (state.searchEdit)
+ traits |= UIAccessibilityTraitSearchField;
+
if (iface->role() == QAccessible::Button)
traits |= UIAccessibilityTraitButton;
diff --git a/src/plugins/platforms/windows/qwindowscursor.cpp b/src/plugins/platforms/windows/qwindowscursor.cpp
index d2460e0640..f5d6c140bf 100644
--- a/src/plugins/platforms/windows/qwindowscursor.cpp
+++ b/src/plugins/platforms/windows/qwindowscursor.cpp
@@ -48,6 +48,13 @@
#include <QtCore/QDebug>
#include <QtCore/QScopedArrayPointer>
+static void initResources()
+{
+#if !defined (Q_OS_WINCE) && !defined (QT_NO_IMAGEFORMAT_PNG)
+ Q_INIT_RESOURCE(cursors);
+#endif
+}
+
QT_BEGIN_NAMESPACE
Q_GUI_EXPORT HBITMAP qt_pixmapToWinHBITMAP(const QPixmap &p, int hbitmapFormat = 0);
@@ -568,6 +575,11 @@ QWindowsWindowCursor QWindowsCursor::pixmapWindowCursor(const QCursor &c)
return it.value();
}
+QWindowsCursor::QWindowsCursor()
+{
+ initResources();
+}
+
/*!
\brief Set a cursor on a window.
diff --git a/src/plugins/platforms/windows/qwindowscursor.h b/src/plugins/platforms/windows/qwindowscursor.h
index c8e1df3f4d..a024646553 100644
--- a/src/plugins/platforms/windows/qwindowscursor.h
+++ b/src/plugins/platforms/windows/qwindowscursor.h
@@ -91,7 +91,7 @@ public:
CursorSuppressed // Cursor suppressed by touch interaction (Windows 8).
};
- QWindowsCursor() {}
+ QWindowsCursor();
void changeCursor(QCursor * widgetCursor, QWindow * widget) Q_DECL_OVERRIDE;
QPoint pos() const Q_DECL_OVERRIDE;
diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp
index dd9b9de0b6..8a80729354 100644
--- a/src/plugins/platforms/windows/qwindowswindow.cpp
+++ b/src/plugins/platforms/windows/qwindowswindow.cpp
@@ -1149,6 +1149,13 @@ void QWindowsWindow::updateTransientParent() const
#endif // !Q_OS_WINCE
}
+static inline bool testShowWithoutActivating(const QWindow *window)
+{
+ // QWidget-attribute Qt::WA_ShowWithoutActivating .
+ const QVariant showWithoutActivating = window->property("_q_showWithoutActivating");
+ return showWithoutActivating.isValid() && showWithoutActivating.toBool();
+}
+
// partially from QWidgetPrivate::show_sys()
void QWindowsWindow::show_sys() const
{
@@ -1180,7 +1187,7 @@ void QWindowsWindow::show_sys() const
} // Qt::WindowMaximized
} // !Qt::WindowMinimized
}
- if (type == Qt::Popup || type == Qt::ToolTip || type == Qt::Tool)
+ if (type == Qt::Popup || type == Qt::ToolTip || type == Qt::Tool || testShowWithoutActivating(w))
sm = SW_SHOWNOACTIVATE;
if (w->windowState() & Qt::WindowMaximized)
diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.cpp b/src/plugins/platforms/xcb/qxcbkeyboard.cpp
index fc3443aba5..dae3a79628 100644
--- a/src/plugins/platforms/xcb/qxcbkeyboard.cpp
+++ b/src/plugins/platforms/xcb/qxcbkeyboard.cpp
@@ -910,6 +910,18 @@ QList<int> QXcbKeyboard::possibleKeys(const QKeyEvent *event) const
if (qtKey == baseQtKey || qtKey == 0)
continue;
+ // catch only more specific shortcuts, i.e. Ctrl+Shift+= also generates Ctrl++ and +,
+ // but Ctrl++ is more specific than +, so we should skip the last one
+ bool ambiguous = false;
+ foreach (int shortcut, result) {
+ if (int(shortcut & ~Qt::KeyboardModifierMask) == qtKey && (shortcut & mods) == mods) {
+ ambiguous = true;
+ break;
+ }
+ }
+ if (ambiguous)
+ continue;
+
result += (qtKey + mods);
}
}