From 3ad6fef72055f7f6912fd66e4be13d65e8875638 Mon Sep 17 00:00:00 2001 From: Richard Moe Gustavsen Date: Wed, 10 Aug 2011 10:18:15 +0200 Subject: Cocoa: change usage of deprecated API (scrolling) in Lion Apple changed the API for pixel based scrolling, which results in runtime warnings on the command line. This patch will make Qt use the new API. In addition, apple removed suppert for z-scrolling. Since that was never supported in Qt as well, we also remote code that handles that. RevBy: msorvig --- src/gui/kernel/qcocoaview_mac.mm | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/src/gui/kernel/qcocoaview_mac.mm b/src/gui/kernel/qcocoaview_mac.mm index e32fdeb..0fbae59 100644 --- a/src/gui/kernel/qcocoaview_mac.mm +++ b/src/gui/kernel/qcocoaview_mac.mm @@ -66,9 +66,14 @@ #include @interface NSEvent (Qt_Compile_Leopard_DeviceDelta) + // SnowLeopard: - (CGFloat)deviceDeltaX; - (CGFloat)deviceDeltaY; - (CGFloat)deviceDeltaZ; + // Lion: + - (CGFloat)scrollingDeltaX; + - (CGFloat)scrollingDeltaY; + - (CGFloat)scrollingDeltaZ; @end @interface NSEvent (Qt_Compile_Leopard_Gestures) @@ -614,7 +619,6 @@ static int qCocoaViewCount = 0; int deltaX = 0; int deltaY = 0; - int deltaZ = 0; const EventRef carbonEvent = (EventRef)[theEvent eventRef]; const UInt32 carbonEventKind = carbonEvent ? ::GetEventKind(carbonEvent) : 0; @@ -627,15 +631,20 @@ static int qCocoaViewCount = 0; // It looks like 1/4 degrees per pixel behaves most native. // (NB: Qt expects the unit for delta to be 8 per degree): const int pixelsToDegrees = 2; // 8 * 1/4 - deltaX = [theEvent deviceDeltaX] * pixelsToDegrees; - deltaY = [theEvent deviceDeltaY] * pixelsToDegrees; - deltaZ = [theEvent deviceDeltaZ] * pixelsToDegrees; + if (QSysInfo::MacintoshVersion <= QSysInfo::MV_10_6) { + // Mac OS 10.6 + deltaX = [theEvent deviceDeltaX] * pixelsToDegrees; + deltaY = [theEvent deviceDeltaY] * pixelsToDegrees; + } else { + // Mac OS 10.7+ + deltaX = [theEvent scrollingDeltaX] * pixelsToDegrees; + deltaY = [theEvent scrollingDeltaY] * pixelsToDegrees; + } } else { // carbonEventKind == kEventMouseWheelMoved // Remove acceleration, and use either -120 or 120 as delta: deltaX = qBound(-120, int([theEvent deltaX] * 10000), 120); deltaY = qBound(-120, int([theEvent deltaY] * 10000), 120); - deltaZ = qBound(-120, int([theEvent deltaZ] * 10000), 120); } #ifndef QT_NO_WHEELEVENT @@ -654,13 +663,6 @@ static int qCocoaViewCount = 0; qt_sendSpontaneousEvent(widgetToGetMouse, &qwe); } - if (deltaZ != 0) { - // Qt doesn't explicitly support wheels with a Z component. In a misguided attempt to - // try to be ahead of the pack, I'm adding this extra value. - QWheelEvent qwe(qlocal, qglobal, deltaZ, buttons, keyMods, (Qt::Orientation)3); - qt_sendSpontaneousEvent(widgetToGetMouse, &qwe); - } - if (deltaX != 0 && deltaY != 0) QMacScrollOptimization::performDelayedScroll(); #endif //QT_NO_WHEELEVENT -- cgit v0.12 From 98babb1408712a14098a9a75b31c4e9603afdbc0 Mon Sep 17 00:00:00 2001 From: Chris Meyer Date: Tue, 9 Nov 2010 10:03:26 -0800 Subject: Fix bug QTBUG-13901, Mac style button rect Make sure that clicks in the corners of buttons with Mac style are treated properly. Added test case. --- src/gui/styles/qmacstyle_mac.mm | 2 +- tests/auto/qpushbutton/tst_qpushbutton.cpp | 31 ++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/src/gui/styles/qmacstyle_mac.mm b/src/gui/styles/qmacstyle_mac.mm index 8436856..1c1713c 100644 --- a/src/gui/styles/qmacstyle_mac.mm +++ b/src/gui/styles/qmacstyle_mac.mm @@ -1063,7 +1063,7 @@ bool qt_mac_buttonIsRenderedFlat(const QPushButton *pushButton, const QStyleOpti { QMacStyle *macStyle = qobject_cast(pushButton->style()); if (!macStyle) - return false; + return true; // revert to 'flat' behavior if not Mac style HIThemeButtonDrawInfo bdi; macStyle->d->initHIThemePushButton(option, pushButton, kThemeStateActive, &bdi); return bdi.kind == kThemeBevelButton; diff --git a/tests/auto/qpushbutton/tst_qpushbutton.cpp b/tests/auto/qpushbutton/tst_qpushbutton.cpp index 7742f6b..db4f385 100644 --- a/tests/auto/qpushbutton/tst_qpushbutton.cpp +++ b/tests/auto/qpushbutton/tst_qpushbutton.cpp @@ -91,6 +91,9 @@ private slots: void animateClick(); void toggle(); void clicked(); +#ifdef Q_OS_MAC + void macClicked(); +#endif void toggled(); void isEnabled(); void defaultAndAutoDefault(); @@ -469,6 +472,34 @@ void tst_QPushButton::clicked() QCOMPARE( release_count, (uint)10 ); } +#ifdef Q_OS_MAC +// test that the corners of a mac style button are not treated as clicks. +// but that if a style is applied, they are. +void tst_QPushButton::macClicked() +{ + QPushButton *macTestWidget = new QPushButton( "Push button" ); + macTestWidget->show(); + connect( macTestWidget, SIGNAL(clicked()), this, SLOT(onClicked()) ); + + QTest::mouseClick( macTestWidget, Qt::LeftButton, 0, QPoint(1,1) ); + QVERIFY( click_count == 0 ); + + QTest::mouseClick( macTestWidget, Qt::LeftButton, 0, macTestWidget->rect().center() ); + QVERIFY( click_count == 1 ); + + resetCounters(); + macTestWidget->setStyleSheet("background: white;"); + + QTest::mouseClick( macTestWidget, Qt::LeftButton, 0, QPoint(1,1) ); + QVERIFY( click_count == 1 ); + + QTest::mouseClick( macTestWidget, Qt::LeftButton, 0, macTestWidget->rect().center() ); + QVERIFY( click_count == 2 ); + + delete macTestWidget; +} +#endif + /* void tst_QPushButton::group() { -- cgit v0.12 From 6f84e64f3500db9901bb518c8c5bd2ca03fbbf42 Mon Sep 17 00:00:00 2001 From: Jan-Arve Saether Date: Fri, 12 Aug 2011 11:52:15 +0200 Subject: Fix a crash in a11y introduced by d289e54f2d2aa066cb3 The problem was that the patch assumed that all AT clients only called get_accChild() after NotifyWinEvent was called with a negative child id argument. However, some AT clients might call get_accRole() and get_accState() with that negative value. Implementations of QAccessibleInterface::role() should be able to make the assumption that the child index is always valid. The safe solution is to always look for the item in the cache if the child index is negative for all IAccessible functions we implement. If its positive or zero, execute as before. Crash could be reproduced by: 1. Start MS narrator 2. launch examples\dialogs\tabdialog 3. Click the tab labeled "Permissions" *crash* assertion in QList, index out of range. Reviewed-by: Frederik Gladhorn --- src/gui/accessible/qaccessible_win.cpp | 113 +++++++++++++++++++++------------ 1 file changed, 72 insertions(+), 41 deletions(-) diff --git a/src/gui/accessible/qaccessible_win.cpp b/src/gui/accessible/qaccessible_win.cpp index 79ac442..caabae5 100644 --- a/src/gui/accessible/qaccessible_win.cpp +++ b/src/gui/accessible/qaccessible_win.cpp @@ -600,6 +600,35 @@ HRESULT STDMETHODCALLTYPE QWindowsEnumerate::Skip(unsigned long celt) return S_OK; } +struct AccessibleElement { + AccessibleElement(int entryId, QAccessibleInterface *accessible) { + if (entryId < 0) { + QPair ref = qAccessibleRecentSentEvents()->value(entryId); + iface = QAccessible::queryAccessibleInterface(ref.first); + entry = ref.second; + cleanupInterface = true; + } else { + iface = accessible; + entry = entryId; + cleanupInterface = false; + } + } + + QString text(QAccessible::Text t) const { + return iface ? iface->text(t, entry) : QString(); + } + + ~AccessibleElement() { + if (cleanupInterface) + delete iface; + } + + QAccessibleInterface *iface; + int entry; +private: + bool cleanupInterface; +}; + /* */ class QWindowsAccessible : public IAccessible, IOleWindow, QAccessible @@ -998,7 +1027,8 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::accLocation(long *pxLeft, long *py if (!accessible->isValid()) return E_FAIL; - QRect rect = accessible->rect(varID.lVal); + AccessibleElement elem(varID.lVal, accessible); + QRect rect = elem.iface ? elem.iface->rect(elem.entry) : QRect(); if (rect.isValid()) { *pxLeft = rect.x(); *pyTop = rect.y(); @@ -1101,25 +1131,12 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accChild(VARIANT varChildID, I int childIndex = varChildID.lVal; QAccessibleInterface *acc = 0; - if (childIndex < 0) { - const int entry = childIndex; - QPair ref = qAccessibleRecentSentEvents()->value(entry); - if (ref.first) { - acc = queryAccessibleInterface(ref.first); - if (acc && ref.second) { - if (ref.second) { - QAccessibleInterface *res; - int index = acc->navigate(Child, ref.second, &res); - delete acc; - if (index == -1) - return E_INVALIDARG; - acc = res; - } - } - } - } else { - RelationFlag rel = childIndex ? Child : Self; - accessible->navigate(rel, childIndex, &acc); + AccessibleElement elem(childIndex, accessible); + if (elem.iface) { + RelationFlag rel = elem.entry ? Child : Self; + int index = elem.iface->navigate(rel, elem.entry, &acc); + if (index == -1) + return E_INVALIDARG; } if (acc) { @@ -1171,7 +1188,9 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::accDoDefaultAction(VARIANT varID) if (!accessible->isValid()) return E_FAIL; - return accessible->doAction(DefaultAction, varID.lVal, QVariantList()) ? S_OK : S_FALSE; + AccessibleElement elem(varID.lVal, accessible); + const bool res = elem.iface ? elem.iface->doAction(DefaultAction, elem.entry, QVariantList()) : false; + return res ? S_OK : S_FALSE; } HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accDefaultAction(VARIANT varID, BSTR* pszDefaultAction) @@ -1180,7 +1199,8 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accDefaultAction(VARIANT varID if (!accessible->isValid()) return E_FAIL; - QString def = accessible->actionText(DefaultAction, Name, varID.lVal); + AccessibleElement elem(varID.lVal, accessible); + QString def = elem.iface ? elem.iface->actionText(DefaultAction, Name, elem.entry) : QString(); if (def.isEmpty()) { *pszDefaultAction = 0; return S_FALSE; @@ -1196,7 +1216,8 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accDescription(VARIANT varID, if (!accessible->isValid()) return E_FAIL; - QString descr = accessible->text(Description, varID.lVal); + AccessibleElement elem(varID.lVal, accessible); + QString descr = elem.text(Description); if (descr.size()) { *pszDescription = QStringToBSTR(descr); return S_OK; @@ -1212,7 +1233,8 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accHelp(VARIANT varID, BSTR *p if (!accessible->isValid()) return E_FAIL; - QString help = accessible->text(Help, varID.lVal); + AccessibleElement elem(varID.lVal, accessible); + QString help = elem.text(Help); if (help.size()) { *pszHelp = QStringToBSTR(help); return S_OK; @@ -1233,7 +1255,8 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accKeyboardShortcut(VARIANT va if (!accessible->isValid()) return E_FAIL; - QString sc = accessible->text(Accelerator, varID.lVal); + AccessibleElement elem(varID.lVal, accessible); + QString sc = elem.text(Accelerator); if (sc.size()) { *pszKeyboardShortcut = QStringToBSTR(sc); return S_OK; @@ -1249,7 +1272,8 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accName(VARIANT varID, BSTR* p if (!accessible->isValid()) return E_FAIL; - QString n = accessible->text(Name, varID.lVal); + AccessibleElement elem(varID.lVal, accessible); + QString n = elem.text(Name); if (n.size()) { *pszName = QStringToBSTR(n); return S_OK; @@ -1271,7 +1295,8 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accRole(VARIANT varID, VARIANT if (!accessible->isValid()) return E_FAIL; - Role role = accessible->role(varID.lVal); + AccessibleElement elem(varID.lVal, accessible); + Role role = elem.iface ? elem.iface->role(elem.entry) : NoRole; if (role != NoRole) { if (role == LayeredPane) role = QAccessible::Pane; @@ -1290,7 +1315,8 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accState(VARIANT varID, VARIAN return E_FAIL; (*pvarState).vt = VT_I4; - (*pvarState).lVal = accessible->state(varID.lVal); + AccessibleElement elem(varID.lVal, accessible); + (*pvarState).lVal = elem.iface ? elem.iface->state(elem.entry) : 0; return S_OK; } @@ -1300,7 +1326,8 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accValue(VARIANT varID, BSTR* if (!accessible->isValid()) return E_FAIL; - QString value = accessible->text(Value, varID.lVal); + AccessibleElement elem(varID.lVal, accessible); + QString value = elem.text(Value); if (!value.isNull()) { *pszValue = QStringToBSTR(value); return S_OK; @@ -1324,19 +1351,23 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::accSelect(long flagsSelect, VARIAN bool res = false; - if (flagsSelect & SELFLAG_TAKEFOCUS) - res = accessible->doAction(SetFocus, varID.lVal, QVariantList()); - if (flagsSelect & SELFLAG_TAKESELECTION) { - accessible->doAction(ClearSelection, 0, QVariantList()); - res = accessible->doAction(AddToSelection, varID.lVal, QVariantList()); + AccessibleElement elem(varID.lVal, accessible); + QAccessibleInterface *acc = elem.iface; + if (acc) { + const int entry = elem.entry; + if (flagsSelect & SELFLAG_TAKEFOCUS) + res = acc->doAction(SetFocus, entry, QVariantList()); + if (flagsSelect & SELFLAG_TAKESELECTION) { + acc->doAction(ClearSelection, 0, QVariantList()); //### bug, 0 should be entry?? + res = acc->doAction(AddToSelection, entry, QVariantList()); + } + if (flagsSelect & SELFLAG_EXTENDSELECTION) + res = acc->doAction(ExtendSelection, entry, QVariantList()); + if (flagsSelect & SELFLAG_ADDSELECTION) + res = acc->doAction(AddToSelection, entry, QVariantList()); + if (flagsSelect & SELFLAG_REMOVESELECTION) + res = acc->doAction(RemoveSelection, entry, QVariantList()); } - if (flagsSelect & SELFLAG_EXTENDSELECTION) - res = accessible->doAction(ExtendSelection, varID.lVal, QVariantList()); - if (flagsSelect & SELFLAG_ADDSELECTION) - res = accessible->doAction(AddToSelection, varID.lVal, QVariantList()); - if (flagsSelect & SELFLAG_REMOVESELECTION) - res = accessible->doAction(RemoveSelection, varID.lVal, QVariantList()); - return res ? S_OK : S_FALSE; } -- cgit v0.12