diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-07 11:48:25 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-07 11:48:25 +0000 |
commit | 9c0049cfae49c8e4ddef9125a69db2ad134c10c6 (patch) | |
tree | 812a86c0eee63dfc5ace12f2622ed3ce9cd3d680 /vcl | |
parent | Releasing progress-linux version 4:24.2.3-2~progress7.99u1. (diff) | |
download | libreoffice-9c0049cfae49c8e4ddef9125a69db2ad134c10c6.tar.xz libreoffice-9c0049cfae49c8e4ddef9125a69db2ad134c10c6.zip |
Merging upstream version 4:24.2.4.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vcl')
44 files changed, 368 insertions, 175 deletions
diff --git a/vcl/inc/osx/a11ywrapper.h b/vcl/inc/osx/a11ywrapper.h index 1eb4039c57..48fdd8e2a5 100644 --- a/vcl/inc/osx/a11ywrapper.h +++ b/vcl/inc/osx/a11ywrapper.h @@ -67,6 +67,7 @@ struct ReferenceWrapper ReferenceWrapper maReferenceWrapper; BOOL mActsAsRadioGroup; BOOL mIsTableCell; + BOOL mIsDisposed; } // NSAccessibility Protocol -(id)accessibilityAttributeValue:(NSString *)attribute; @@ -101,6 +102,7 @@ struct ReferenceWrapper -(NSWindow*)windowForParent; -(id)init; -(id)initWithAccessibleContext: (css::uno::Reference < css::accessibility::XAccessibleContext >) anAccessibleContext; +-(void)setDisposed; -(void) setDefaults: (css::uno::Reference < css::accessibility::XAccessibleContext >) rxAccessibleContext; +(void)setPopupMenuOpen:(BOOL)popupMenuOpen; -(css::accessibility::XAccessibleAction *)accessibleAction; diff --git a/vcl/inc/qt5/QtTransferable.hxx b/vcl/inc/qt5/QtTransferable.hxx index 5f1533dd59..5687fa06df 100644 --- a/vcl/inc/qt5/QtTransferable.hxx +++ b/vcl/inc/qt5/QtTransferable.hxx @@ -34,13 +34,23 @@ class QtTransferable : public cppu::WeakImplHelper<css::datatransfer::XTransfera QtTransferable(const QtTransferable&) = delete; const QMimeData* m_pMimeData; - osl::Mutex m_aMutex; - bool m_bProvideUTF16FromOtherEncoding; - css::uno::Sequence<css::datatransfer::DataFlavor> m_aMimeTypeSeq; + +protected: + /** Sets new mime data. + * Since data flavors supported by this class depend on the mime data, + * results from previous calls to the public methods of this + * class are no longer valid after setting new mime data using this method. + * + * Subclasses that set new mime data must ensure that no data race exists + * on m_pMimeData. + * (For the current only subclass doing so, QtClipboardTransferable, all access + * to m_pMimeData happens with the SolarMutex held.) + */ + void setMimeData(const QMimeData* pMimeData) { m_pMimeData = pMimeData; } + const QMimeData* mimeData() const { return m_pMimeData; } public: QtTransferable(const QMimeData* pMimeData); - const QMimeData* mimeData() const { return m_pMimeData; } css::uno::Sequence<css::datatransfer::DataFlavor> SAL_CALL getTransferDataFlavors() override; sal_Bool SAL_CALL isDataFlavorSupported(const css::datatransfer::DataFlavor& rFlavor) override; @@ -54,21 +64,24 @@ public: * the QClipboard's object thread, which is the QApplication's thread, so all of * the access has to go through RunInMainThread(). * - * If we detect a QMimeData change, we simply drop reporting any content. In theory - * we can recover in the case where there hadn't been any calls of the XTransferable - * interface, but currently we don't. But we ensure to never report mixed content, - * so we'll just cease operation on QMimeData change. + * If we detect a QMimeData change, the mime data is updated with the new one from + * the system clipboard. Note however that this means that results of any previous + * calls of the XTransferable interface will be out of sync with the newly set mime + * data, so this scenario should generally be avoided. **/ class QtClipboardTransferable final : public QtTransferable { // to detect in-flight QMimeData changes const QClipboard::Mode m_aMode; - bool hasInFlightChanged() const; + void ensureConsistencyWithSystemClipboard(); public: explicit QtClipboardTransferable(const QClipboard::Mode aMode, const QMimeData* pMimeData); + // whether pMimeData are the current mime data + bool hasMimeData(const QMimeData* pMimeData) const; + // these are the same then QtTransferable, except they go through RunInMainThread css::uno::Sequence<css::datatransfer::DataFlavor> SAL_CALL getTransferDataFlavors() override; sal_Bool SAL_CALL isDataFlavorSupported(const css::datatransfer::DataFlavor& rFlavor) override; diff --git a/vcl/inc/salvtables.hxx b/vcl/inc/salvtables.hxx index 4074e097a4..d6d3a90ce2 100644 --- a/vcl/inc/salvtables.hxx +++ b/vcl/inc/salvtables.hxx @@ -922,6 +922,8 @@ public: return 20 * (pDefault ? pDefault->GetDPIScaleFactor() : 1.0); } + void set_max_drop_down_rows(int nRows) override { m_xComboBox->SetDropDownLineCount(nRows); } + void CallHandleEventListener(VclWindowEvent& rEvent) { if (rEvent.GetId() == VclEventId::DropdownPreOpen diff --git a/vcl/osx/DataFlavorMapping.cxx b/vcl/osx/DataFlavorMapping.cxx index 361e268bcd..ade3f48dd1 100644 --- a/vcl/osx/DataFlavorMapping.cxx +++ b/vcl/osx/DataFlavorMapping.cxx @@ -732,10 +732,7 @@ NSArray* DataFlavorMapper::flavorSequenceToTypesArray(const css::uno::Sequence<c const NSString* str = openOfficeToSystemFlavor(flavors[i], bNeedDummyInternalFlavor, bIsSystemClipboard); if (str != nullptr) - { - [str retain]; [array addObject: str]; - } } } diff --git a/vcl/osx/a11yactionwrapper.mm b/vcl/osx/a11yactionwrapper.mm index 9bea25c119..f9c5089a19 100644 --- a/vcl/osx/a11yactionwrapper.mm +++ b/vcl/osx/a11yactionwrapper.mm @@ -55,16 +55,22 @@ NSMutableArray * actionNames = [ [ NSMutableArray alloc ] init ]; if ( [ wrapper accessibleAction ] ) { for ( int cnt = 0; cnt < [ wrapper accessibleAction ] -> getAccessibleActionCount(); cnt++ ) { - [ actionNames addObject: [ AquaA11yActionWrapper nativeActionNameFor: CreateNSString ( [ wrapper accessibleAction ] -> getAccessibleActionDescription ( cnt ) ) ] ]; + // Related tdf#158914: explicitly call autorelease selector + // CreateNSString() is not a getter. It expects the caller to + // release the returned string. + [ actionNames addObject: [ AquaA11yActionWrapper nativeActionNameFor: [ CreateNSString ( [ wrapper accessibleAction ] -> getAccessibleActionDescription ( cnt ) ) autorelease ] ] ]; } } - return actionNames; + return [actionNames autorelease]; } +(void)doAction:(NSString *)action ofElement:(AquaA11yWrapper *)wrapper { if ( [ wrapper accessibleAction ] ) { for ( int cnt = 0; cnt < [ wrapper accessibleAction ] -> getAccessibleActionCount(); cnt++ ) { - if ( [ action isEqualToString: [ AquaA11yActionWrapper nativeActionNameFor: CreateNSString ( [ wrapper accessibleAction ] -> getAccessibleActionDescription ( cnt ) ) ] ] ) { + // Related tdf#158914: explicitly call autorelease selector + // CreateNSString() is not a getter. It expects the caller to + // release the returned string. + if ( [ action isEqualToString: [ AquaA11yActionWrapper nativeActionNameFor: [ CreateNSString ( [ wrapper accessibleAction ] -> getAccessibleActionDescription ( cnt ) ) autorelease ] ] ] ) { [ wrapper accessibleAction ] -> doAccessibleAction ( cnt ); break; } diff --git a/vcl/osx/a11ycomponentwrapper.mm b/vcl/osx/a11ycomponentwrapper.mm index d9d6db1754..15363a6687 100644 --- a/vcl/osx/a11ycomponentwrapper.mm +++ b/vcl/osx/a11ycomponentwrapper.mm @@ -48,7 +48,10 @@ using namespace ::com::sun::star::uno; +(id)descriptionAttributeForElement:(AquaA11yWrapper *)wrapper { if ( [ wrapper accessibleExtendedComponent ] ) { - return CreateNSString ( [ wrapper accessibleExtendedComponent ] -> getToolTipText() ); + // Related tdf#158914: explicitly call autorelease selector + // CreateNSString() is not a getter. It expects the caller to + // release the returned string. + return [ CreateNSString ( [ wrapper accessibleExtendedComponent ] -> getToolTipText() ) autorelease ]; } else { return nil; } diff --git a/vcl/osx/a11yfactory.mm b/vcl/osx/a11yfactory.mm index 0783252c7e..27b5ad2d81 100644 --- a/vcl/osx/a11yfactory.mm +++ b/vcl/osx/a11yfactory.mm @@ -140,7 +140,6 @@ static bool enabled = false; } else { aWrapper = [ [ AquaA11yWrapper alloc ] initWithAccessibleContext: rxAccessibleContext ]; } - [ nativeRole release ]; [ aWrapper setActsAsRadioGroup: asRadioGroup ]; #if 0 /* #i102033# NSAccessibility does not seemt to know an equivalent for transient children. @@ -169,8 +168,8 @@ static bool enabled = false; // TODO: when RADIO_BUTTON search for associated RadioGroup-wrapper and delete that as well AquaA11yWrapper * theWrapper = [ AquaA11yFactory wrapperForAccessibleContext: rxAccessibleContext createIfNotExists: NO ]; if ( theWrapper != nil ) { - NSAccessibilityPostNotification( theWrapper, NSAccessibilityUIElementDestroyedNotification ); [ [ AquaA11yFactory allWrapper ] removeObjectForKey: [ AquaA11yFactory keyForAccessibleContext: rxAccessibleContext ] ]; + [ theWrapper setDisposed ]; [ theWrapper release ]; } } diff --git a/vcl/osx/a11yrolehelper.mm b/vcl/osx/a11yrolehelper.mm index a1cf62f327..5b621a74e2 100644 --- a/vcl/osx/a11yrolehelper.mm +++ b/vcl/osx/a11yrolehelper.mm @@ -144,17 +144,14 @@ using namespace ::com::sun::star::uno; id nativeRole = [ AquaA11yRoleHelper simpleMapNativeRoleFrom: accessibleContext ]; if ( accessibleContext -> getAccessibleRole() == AccessibleRole::LABEL ) { if ( accessibleContext -> getAccessibleChildCount() > 0 ) { - [ nativeRole release ]; nativeRole = NSAccessibilityOutlineRole; } else if ( accessibleContext -> getAccessibleParent().is() ) { Reference < XAccessibleContext > rxParentContext = accessibleContext -> getAccessibleParent() -> getAccessibleContext(); if ( rxParentContext.is() ) { NSString * roleParent = static_cast<NSString *>([ AquaA11yRoleHelper simpleMapNativeRoleFrom: rxParentContext.get() ]); if ( [ roleParent isEqualToString: NSAccessibilityOutlineRole ] ) { - [ nativeRole release ]; nativeRole = NSAccessibilityRowRole; } - [ roleParent release ]; } } } else if ( accessibleContext -> getAccessibleRole() == AccessibleRole::COMBO_BOX ) { @@ -165,7 +162,6 @@ using namespace ::com::sun::star::uno; if ( rxAccessibleContext.is() && rxAccessibleContext -> getAccessibleRole() == AccessibleRole::TEXT ) { sal_Int64 nStateSet = rxAccessibleContext -> getAccessibleStateSet(); if ( !(nStateSet & AccessibleStateType::EDITABLE ) ) { - [ nativeRole release ]; nativeRole = NSAccessibilityPopUpButtonRole; } } diff --git a/vcl/osx/a11yselectionwrapper.mm b/vcl/osx/a11yselectionwrapper.mm index 9d3beee2d3..4c9d1c7bfc 100644 --- a/vcl/osx/a11yselectionwrapper.mm +++ b/vcl/osx/a11yselectionwrapper.mm @@ -34,10 +34,13 @@ using namespace ::com::sun::star::uno; Reference< XAccessibleSelection > xAccessibleSelection = [ wrapper accessibleSelection ]; if( xAccessibleSelection.is() ) { - NSMutableArray * children = [ [ NSMutableArray alloc ] init ]; try { sal_Int64 n = xAccessibleSelection -> getSelectedAccessibleChildCount(); + // Related tdf#158914: implicitly call autorelease selector + // Callers expect this selector to return an autoreleased object. + NSMutableArray * children = [ NSMutableArray arrayWithCapacity: n ]; + // Fix hanging when selecting a column or row in Calc // When a Calc column is selected, the child count will be // at least a million. Constructing that many C++ Calc objects @@ -49,7 +52,12 @@ using namespace ::com::sun::star::uno; n = MAXIMUM_ACCESSIBLE_TABLE_CELLS; for ( sal_Int64 i=0 ; i < n ; ++i ) { - [ children addObject: [ AquaA11yFactory wrapperForAccessible: xAccessibleSelection -> getSelectedAccessibleChild( i ) ] ]; + // Related tdf#158914: explicitly call release selector + // [ AquaA11yFactory wrapperForAccessible: ] is not a getter. + // It expects the caller to release the returned object. + id child_wrapper = [ AquaA11yFactory wrapperForAccessible: xAccessibleSelection -> getSelectedAccessibleChild( i ) ]; + [ children addObject: child_wrapper ]; + [ child_wrapper release ]; } return children; diff --git a/vcl/osx/a11ytextattributeswrapper.mm b/vcl/osx/a11ytextattributeswrapper.mm index 4404dc6463..11b205a803 100644 --- a/vcl/osx/a11ytextattributeswrapper.mm +++ b/vcl/osx/a11ytextattributeswrapper.mm @@ -210,7 +210,10 @@ using namespace ::com::sun::star::uno; } else if ( property.Name == "CharFontName" ) { OUString fontname; property.Value >>= fontname; - [fontDescriptor setName:CreateNSString(fontname)]; + // Related tdf#158914: explicitly call autorelease selector + // CreateNSString() is not a getter. It expects the caller to + // release the returned string. + [ fontDescriptor setName: [ CreateNSString(fontname) autorelease ] ]; } else if ( property.Name == "CharWeight" ) { [fontDescriptor setBold:[AquaA11yTextAttributesWrapper convertBoldStyle:property]]; } else if ( property.Name == "CharPosture" ) { @@ -313,8 +316,11 @@ using namespace ::com::sun::star::uno; int endIndex = loc + len; int currentIndex = loc; try { - NSString * myString = CreateNSString ( [ wrapper accessibleText ] -> getText() ); // TODO: dirty fix for i87817 - string = [ [ NSMutableAttributedString alloc ] initWithString: CreateNSString ( [ wrapper accessibleText ] -> getTextRange ( loc, loc + len ) ) ]; + // Related tdf#158914: explicitly call autorelease selector + // CreateNSString() is not a getter. It expects the caller to + // release the returned string. + NSString * myString = [ CreateNSString ( [ wrapper accessibleText ] -> getText() ) autorelease ]; // TODO: dirty fix for i87817 + string = [ [ NSMutableAttributedString alloc ] initWithString: [ CreateNSString ( [ wrapper accessibleText ] -> getTextRange ( loc, loc + len ) ) autorelease ] ]; [ string autorelease ]; if ( [ wrapper accessibleTextAttributes ] && [myString characterAtIndex:0] != 57361) { // TODO: dirty fix for i87817 [ string beginEditing ]; diff --git a/vcl/osx/a11ytextwrapper.mm b/vcl/osx/a11ytextwrapper.mm index cfd4ae7c1c..5a932d38a2 100644 --- a/vcl/osx/a11ytextwrapper.mm +++ b/vcl/osx/a11ytextwrapper.mm @@ -39,7 +39,10 @@ using namespace ::com::sun::star::uno; @implementation AquaA11yTextWrapper : NSObject +(id)valueAttributeForElement:(AquaA11yWrapper *)wrapper { - return CreateNSString ( [ wrapper accessibleText ] -> getText() ); + // Related tdf#158914: explicitly call autorelease selector + // CreateNSString() is not a getter. It expects the caller to + // release the returned string. + return [ CreateNSString ( [ wrapper accessibleText ] -> getText() ) autorelease ]; } +(void)setValueAttributeForElement:(AquaA11yWrapper *)wrapper to:(id)value @@ -54,7 +57,10 @@ using namespace ::com::sun::star::uno; } +(id)selectedTextAttributeForElement:(AquaA11yWrapper *)wrapper { - return CreateNSString ( [ wrapper accessibleText ] -> getSelectedText() ); + // Related tdf#158914: explicitly call autorelease selector + // CreateNSString() is not a getter. It expects the caller to + // release the returned string. + return [ CreateNSString ( [ wrapper accessibleText ] -> getSelectedText() ) autorelease ]; } +(void)setSelectedTextAttributeForElement:(AquaA11yWrapper *)wrapper to:(id)value { @@ -175,9 +181,12 @@ using namespace ::com::sun::star::uno; +(id)stringForRangeAttributeForElement:(AquaA11yWrapper *)wrapper forParameter:(id)range { int loc = [ range rangeValue ].location; int len = [ range rangeValue ].length; - NSMutableString * textRange = [ [ NSMutableString alloc ] init ]; + NSMutableString * textRange = [ NSMutableString string ]; try { - [ textRange appendString: CreateNSString ( [ wrapper accessibleText ] -> getTextRange ( loc, loc + len ) ) ]; + // Related tdf#158914: explicitly call autorelease selector + // CreateNSString() is not a getter. It expects the caller to + // release the returned string. + [ textRange appendString: [ CreateNSString ( [ wrapper accessibleText ] -> getTextRange ( loc, loc + len ) ) autorelease ] ]; } catch ( IndexOutOfBoundsException & ) { // empty } diff --git a/vcl/osx/a11ywrapper.mm b/vcl/osx/a11ywrapper.mm index df1d3690df..9ad6f0d473 100644 --- a/vcl/osx/a11ywrapper.mm +++ b/vcl/osx/a11ywrapper.mm @@ -84,10 +84,28 @@ static std::ostream &operator<<(std::ostream &s, NSObject *obj) { return self; } +-(void)setDisposed { + // Related: tdf#148453 Acquire solar mutex during native accessibility calls + SolarMutexGuard aGuard; + + mIsDisposed = YES; + + // Release all strong C++ references + maReferenceWrapper = ReferenceWrapper(); + + // Related tdf@158914 avoid resurrecting object's C++ references + // Posting an NSAccessibilityUIElementDestroyedNotification + // notification causes [ AquaA11yWrapper isAccessibilityElement ] + // to be called on the object so mark the object as disposed + // before posting the destroyed notification. + NSAccessibilityPostNotification( self, NSAccessibilityUIElementDestroyedNotification ); +} + -(void) setDefaults: (Reference < XAccessibleContext >) rxAccessibleContext { mActsAsRadioGroup = NO; maReferenceWrapper.rAccessibleContext = rxAccessibleContext; mIsTableCell = NO; + mIsDisposed = NO; // Querying all supported interfaces try { // XAccessibleComponent @@ -230,7 +248,6 @@ static std::ostream &operator<<(std::ostream &s, NSObject *obj) { if ( ! [ subRole isEqualToString: @"" ] ) { return subRole; } else { - [ subRole release ]; SAL_WNODEPRECATED_DECLARATIONS_PUSH //TODO: 10.10 accessibilityAttributeValue: return [ super accessibilityAttributeValue: NSAccessibilitySubroleAttribute ]; @@ -240,7 +257,10 @@ static std::ostream &operator<<(std::ostream &s, NSObject *obj) { } -(id)titleAttribute { - return CreateNSString ( [ self accessibleContext ] -> getAccessibleName() ); + // Related tdf#158914: explicitly call autorelease selector + // CreateNSString() is not a getter. It expects the caller to + // release the returned string. + return [ CreateNSString ( [ self accessibleContext ] -> getAccessibleName() ) autorelease ]; } -(id)descriptionAttribute { @@ -249,7 +269,10 @@ static std::ostream &operator<<(std::ostream &s, NSObject *obj) { } else if ( [ self accessibleExtendedComponent ] ) { return [ AquaA11yComponentWrapper descriptionAttributeForElement: self ]; } else { - return CreateNSString ( [ self accessibleContext ] -> getAccessibleDescription() ); + // Related tdf#158914: explicitly call autorelease selector + // CreateNSString() is not a getter. It expects the caller to + // release the returned string. + return [ CreateNSString ( [ self accessibleContext ] -> getAccessibleDescription() ) autorelease ]; } } @@ -330,14 +353,15 @@ static std::ostream &operator<<(std::ostream &s, NSObject *obj) { } } } - return children; + return [children autorelease]; } else if ( [ self accessibleTable ] ) { AquaA11yTableWrapper* pTable = [self isKindOfClass: [AquaA11yTableWrapper class]] ? static_cast<AquaA11yTableWrapper*>(self) : nil; return [ AquaA11yTableWrapper childrenAttributeForElement: pTable ]; } else { + NSMutableArray * children = [ [ NSMutableArray alloc ] init ]; + try { - NSMutableArray * children = [ [ NSMutableArray alloc ] init ]; Reference< XAccessibleContext > xContext( [ self accessibleContext ] ); try { @@ -375,12 +399,13 @@ static std::ostream &operator<<(std::ostream &s, NSObject *obj) { } } - [ children autorelease ]; - return NSAccessibilityUnignoredChildren( children ); + return NSAccessibilityUnignoredChildren( [ children autorelease ] ); } catch (const Exception &) { // TODO: Log - return nil; } + + [ children autorelease ]; + return [NSArray array]; } } @@ -426,7 +451,10 @@ static std::ostream &operator<<(std::ostream &s, NSObject *obj) { } -(id)helpAttribute { - return CreateNSString ( [ self accessibleContext ] -> getAccessibleDescription() ); + // Related tdf#158914: explicitly call autorelease selector + // CreateNSString() is not a getter. It expects the caller to + // release the returned string. + return [ CreateNSString ( [ self accessibleContext ] -> getAccessibleDescription() ) autorelease ]; } -(id)roleDescriptionAttribute { @@ -450,15 +478,11 @@ static std::ostream &operator<<(std::ostream &s, NSObject *obj) { // build string NSNumber * nIndex = [ NSNumber numberWithInt: index ]; NSNumber * nGroupsize = [ NSNumber numberWithInt: [ children count ] ]; - NSMutableString * value = [ [ NSMutableString alloc ] init ]; + NSMutableString * value = [ NSMutableString string ]; [ value appendString: @"radio button " ]; [ value appendString: [ nIndex stringValue ] ]; [ value appendString: @" of " ]; [ value appendString: [ nGroupsize stringValue ] ]; - // clean up and return string - [ nIndex release ]; - [ nGroupsize release ]; - [ children release ]; return value; } else { return [ AquaA11yRoleHelper getRoleDescriptionFrom: @@ -643,9 +667,6 @@ static std::ostream &operator<<(std::ostream &s, NSObject *obj) { titleElement = [ AquaA11yFactory wrapperForAccessibleContext: rxAccessible -> getAccessibleContext() ]; } } - if ( title ) { - [ title release ]; - } return titleElement; } else { return nil; @@ -688,6 +709,8 @@ static std::ostream &operator<<(std::ostream &s, NSObject *obj) { -(id)accessibilityAttributeValue:(NSString *)attribute { // Related: tdf#148453 Acquire solar mutex during native accessibility calls SolarMutexGuard aGuard; + if ( mIsDisposed ) + return nil; SAL_INFO("vcl.a11y", "[" << self << " accessibilityAttributeValue:" << attribute << "]"); // #i90575# guard NSAccessibility protocol against unwanted access @@ -721,13 +744,15 @@ static std::ostream &operator<<(std::ostream &s, NSObject *obj) { -(BOOL)accessibilityIsIgnored { // Related: tdf#148453 Acquire solar mutex during native accessibility calls SolarMutexGuard aGuard; + if ( mIsDisposed ) + return YES; SAL_INFO("vcl.a11y", "[" << self << " accessibilityIsIgnored]"); // #i90575# guard NSAccessibility protocol against unwanted access if ( isPopupMenuOpen ) { return NO; } - bool ignored = false; + BOOL ignored = false; try { sal_Int16 nRole = [ self accessibleContext ] -> getAccessibleRole(); switch ( nRole ) { @@ -755,6 +780,8 @@ static std::ostream &operator<<(std::ostream &s, NSObject *obj) { -(NSArray *)accessibilityAttributeNames { // Related: tdf#148453 Acquire solar mutex during native accessibility calls SolarMutexGuard aGuard; + if ( mIsDisposed ) + return nil; SAL_INFO("vcl.a11y", "[" << self << " accessibilityAttributeNames]"); // #i90575# guard NSAccessibility protocol against unwanted access @@ -818,21 +845,9 @@ static std::ostream &operator<<(std::ostream &s, NSObject *obj) { if ( [ self accessibleValue ] ) { [ AquaA11yValueWrapper addAttributeNamesTo: attributeNames ]; } - if ( nativeSubrole ) { - [ nativeSubrole release ]; - } - if ( title ) { - [ title release ]; - } // Related: tdf#153374 Don't release autoreleased attributeNames return attributeNames; } catch ( DisposedException & ) { // Object is no longer available - if ( nativeSubrole ) { - [ nativeSubrole release ]; - } - if ( title ) { - [ title release ]; - } // Related: tdf#153374 Don't release autoreleased attributeNames // Also, return an autoreleased empty array instead of a retained array. [ AquaA11yFactory removeFromWrapperRepositoryFor: [ self accessibleContext ] ]; @@ -843,6 +858,8 @@ static std::ostream &operator<<(std::ostream &s, NSObject *obj) { -(BOOL)accessibilityIsAttributeSettable:(NSString *)attribute { // Related: tdf#148453 Acquire solar mutex during native accessibility calls SolarMutexGuard aGuard; + if ( mIsDisposed ) + return NO; SAL_INFO("vcl.a11y", "[" << self << " accessibilityAttributeIsSettable:" << attribute << "]"); bool isSettable = false; @@ -864,6 +881,8 @@ static std::ostream &operator<<(std::ostream &s, NSObject *obj) { -(NSArray *)accessibilityParameterizedAttributeNames { // Related: tdf#148453 Acquire solar mutex during native accessibility calls SolarMutexGuard aGuard; + if ( mIsDisposed ) + return [ NSArray array ]; SAL_INFO("vcl.a11y", "[" << self << " accessibilityParameterizedAttributeNames]"); NSMutableArray * attributeNames = [ NSMutableArray array ]; @@ -877,6 +896,8 @@ static std::ostream &operator<<(std::ostream &s, NSObject *obj) { -(id)accessibilityAttributeValue:(NSString *)attribute forParameter:(id)parameter { // Related: tdf#148453 Acquire solar mutex during native accessibility calls SolarMutexGuard aGuard; + if ( mIsDisposed ) + return nil; SAL_INFO("vcl.a11y", "[" << self << " accessibilityAttributeValue:" << attribute << " forParameter:" << (static_cast<NSObject*>(parameter)) << "]"); SEL methodSelector = [ self selectorForAttribute: attribute asGetter: YES withGetterParameter: YES ]; @@ -903,6 +924,8 @@ static std::ostream &operator<<(std::ostream &s, NSObject *obj) { -(void)accessibilitySetValue:(id)value forAttribute:(NSString *)attribute { // Related: tdf#148453 Acquire solar mutex during native accessibility calls SolarMutexGuard aGuard; + if ( mIsDisposed ) + return; SAL_INFO("vcl.a11y", "[" << self << " accessibilitySetValue:" << (static_cast<NSObject*>(value)) << " forAttribute:" << attribute << "]"); SEL methodSelector = [ self selectorForAttribute: attribute asGetter: NO withGetterParameter: NO ]; @@ -923,6 +946,8 @@ static std::ostream &operator<<(std::ostream &s, NSObject *obj) { -(id)accessibilityFocusedUIElement { // Related: tdf#148453 Acquire solar mutex during native accessibility calls SolarMutexGuard aGuard; + if ( mIsDisposed ) + return nil; SAL_INFO("vcl.a11y", "[" << self << " accessibilityFocusedUIElement]"); // #i90575# guard NSAccessibility protocol against unwanted access @@ -977,9 +1002,6 @@ static std::ostream &operator<<(std::ostream &s, NSObject *obj) { } else if ( enabled && [ self accessibleAction ] ) { wrapper = self ; } - [ parentRole release ]; - [ enabledAttr release ]; - [ role release ]; return wrapper; } @@ -990,6 +1012,8 @@ static std::ostream &operator<<(std::ostream &s, NSObject *obj) { -(BOOL)performAction:(NSString *)action { // Related: tdf#148453 Acquire solar mutex during native accessibility calls SolarMutexGuard aGuard; + if ( mIsDisposed ) + return NO; SAL_INFO("vcl.a11y", "[" << self << " accessibilityPerformAction:" << action << "]"); AquaA11yWrapper * actionResponder = [ self actionResponder ]; @@ -1003,6 +1027,8 @@ static std::ostream &operator<<(std::ostream &s, NSObject *obj) { -(NSArray *)accessibilityActionNames { // Related: tdf#148453 Acquire solar mutex during native accessibility calls SolarMutexGuard aGuard; + if ( mIsDisposed ) + return nil; SAL_INFO("vcl.a11y", "[" << self << " accessibilityActionNames]"); NSArray * actionNames = nil; @@ -1010,7 +1036,7 @@ static std::ostream &operator<<(std::ostream &s, NSObject *obj) { if ( actionResponder ) { actionNames = [ AquaA11yActionWrapper actionNamesForElement: actionResponder ]; } else { - actionNames = [ [ NSArray alloc ] init ]; + actionNames = [ NSArray array ]; } return actionNames; } @@ -1097,13 +1123,10 @@ static Reference < XAccessibleContext > hitTestRunner ( css::awt::Point point, -(id)accessibilityHitTest:(NSPoint)point { // Related: tdf#148453 Acquire solar mutex during native accessibility calls SolarMutexGuard aGuard; + if ( mIsDisposed ) + return nil; SAL_INFO("vcl.a11y", "[" << self << " accessibilityHitTest:" << point << "]"); - static id wrapper = nil; - if ( nil != wrapper ) { - [ wrapper release ]; - wrapper = nil; - } Reference < XAccessibleContext > hitChild; NSRect screenRect = [ [ NSScreen mainScreen ] frame ]; css::awt::Point hitPoint ( static_cast<sal_Int32>(point.x) , static_cast<sal_Int32>(screenRect.size.height - point.y) ); @@ -1141,12 +1164,16 @@ static Reference < XAccessibleContext > hitTestRunner ( css::awt::Point point, hitChild = hitTestRunner ( hitPoint, maReferenceWrapper.rAccessibleContext ); } if ( hitChild.is() ) { - wrapper = [ AquaA11yFactory wrapperForAccessibleContext: hitChild ]; - } - if ( wrapper ) { - [ wrapper retain ]; // TODO: retain only when transient ? + // Related tdf#158914: do not retain wrapper + // [ AquaA11yFactory wrapperForAccessibleContext: ] already retains + // the returned object so retaining it until the next call to this + // selector can lead to a memory leak when dragging selected cells + // in Calc to a new location. So autorelease the object so that + // transient objects stay alive but not past the next clearing of + // the autorelease pool. + return [ [ AquaA11yFactory wrapperForAccessibleContext: hitChild ] autorelease ]; } - return wrapper; + return nil; } #pragma mark - @@ -1548,6 +1575,8 @@ static Reference < XAccessibleContext > hitTestRunner ( css::awt::Point point, { // Related: tdf#148453 Acquire solar mutex during native accessibility calls SolarMutexGuard aGuard; + if ( mIsDisposed ) + return NSZeroRect; try { XAccessibleComponent *pAccessibleComponent = [ self accessibleComponent ]; @@ -1578,6 +1607,11 @@ static Reference < XAccessibleContext > hitTestRunner ( css::awt::Point point, // don't explicitly report (non-)expanded state when not expandable if (aSelector == @selector(isAccessibilityExpanded)) { + // Acquire solar mutex during native accessibility calls + SolarMutexGuard aGuard; + if ( mIsDisposed ) + return NO; + const sal_Int64 nStateSet = [ self accessibleContext ] -> getAccessibleStateSet(); if (!( nStateSet & AccessibleStateType::EXPANDABLE)) return false; diff --git a/vcl/osx/a11ywrapperbutton.mm b/vcl/osx/a11ywrapperbutton.mm index a2c0d0398f..d988e0b644 100644 --- a/vcl/osx/a11ywrapperbutton.mm +++ b/vcl/osx/a11ywrapperbutton.mm @@ -39,6 +39,8 @@ -(NSArray *)accessibilityAttributeNames { // Related: tdf#148453 Acquire solar mutex during native accessibility calls SolarMutexGuard aGuard; + if ( mIsDisposed ) + return [ NSArray array ]; // Default Attributes NSMutableArray * attributeNames = [ NSMutableArray arrayWithArray: [ super accessibilityAttributeNames ] ]; diff --git a/vcl/osx/a11ywrappercheckbox.mm b/vcl/osx/a11ywrappercheckbox.mm index 9e0f221985..7f78e68de8 100644 --- a/vcl/osx/a11ywrappercheckbox.mm +++ b/vcl/osx/a11ywrappercheckbox.mm @@ -39,6 +39,8 @@ -(BOOL)accessibilityIsAttributeSettable:(NSString *)attribute { // Related: tdf#148453 Acquire solar mutex during native accessibility calls SolarMutexGuard aGuard; + if ( mIsDisposed ) + return NO; if ( [ attribute isEqualToString: NSAccessibilityValueAttribute ] ) { return NO; @@ -49,6 +51,8 @@ -(NSArray *)accessibilityAttributeNames { // Related: tdf#148453 Acquire solar mutex during native accessibility calls SolarMutexGuard aGuard; + if ( mIsDisposed ) + return [ NSArray array ]; // Default Attributes NSMutableArray * attributeNames = [ NSMutableArray arrayWithArray: [ super accessibilityAttributeNames ] ]; diff --git a/vcl/osx/a11ywrappercombobox.mm b/vcl/osx/a11ywrappercombobox.mm index bfcef7275e..d9a0727d9d 100644 --- a/vcl/osx/a11ywrappercombobox.mm +++ b/vcl/osx/a11ywrappercombobox.mm @@ -113,6 +113,8 @@ using namespace ::com::sun::star::uno; -(BOOL)accessibilityIsAttributeSettable:(NSString *)attribute { // Related: tdf#148453 Acquire solar mutex during native accessibility calls SolarMutexGuard aGuard; + if ( mIsDisposed ) + return NO; if ( [ self textArea ] != nil && ( [ attribute isEqualToString: NSAccessibilitySelectedTextAttribute ] @@ -126,6 +128,8 @@ using namespace ::com::sun::star::uno; -(void)accessibilitySetValue:(id)value forAttribute:(NSString *)attribute { // Related: tdf#148453 Acquire solar mutex during native accessibility calls SolarMutexGuard aGuard; + if ( mIsDisposed ) + return; if ( [ self textArea ] != nil && ( [ attribute isEqualToString: NSAccessibilitySelectedTextAttribute ] @@ -139,6 +143,8 @@ using namespace ::com::sun::star::uno; -(NSArray *)accessibilityAttributeNames { // Related: tdf#148453 Acquire solar mutex during native accessibility calls SolarMutexGuard aGuard; + if ( mIsDisposed ) + return [ NSArray array ]; // Default Attributes NSMutableArray * attributeNames = [ NSMutableArray arrayWithArray: [ super accessibilityAttributeNames ] ]; diff --git a/vcl/osx/a11ywrappergroup.mm b/vcl/osx/a11ywrappergroup.mm index 7ed70d47ba..f50d23677f 100644 --- a/vcl/osx/a11ywrappergroup.mm +++ b/vcl/osx/a11ywrappergroup.mm @@ -33,6 +33,8 @@ -(NSArray *)accessibilityAttributeNames { // Related: tdf#148453 Acquire solar mutex during native accessibility calls SolarMutexGuard aGuard; + if ( mIsDisposed ) + return [ NSArray array ]; // Default Attributes NSMutableArray * attributeNames = [ NSMutableArray arrayWithArray: [ super accessibilityAttributeNames ] ]; diff --git a/vcl/osx/a11ywrapperlist.mm b/vcl/osx/a11ywrapperlist.mm index 25b3fa37ac..e1c3f4f090 100644 --- a/vcl/osx/a11ywrapperlist.mm +++ b/vcl/osx/a11ywrapperlist.mm @@ -31,6 +31,8 @@ using namespace ::com::sun::star::accessibility; -(NSArray *)accessibilityAttributeNames { // Related: tdf#148453 Acquire solar mutex during native accessibility calls SolarMutexGuard aGuard; + if ( mIsDisposed ) + return [ NSArray array ]; // Default Attributes NSMutableArray * attributeNames = [ NSMutableArray arrayWithArray: [ super accessibilityAttributeNames ] ]; diff --git a/vcl/osx/a11ywrapperradiobutton.mm b/vcl/osx/a11ywrapperradiobutton.mm index 5022cc18c2..bd2d8bde68 100644 --- a/vcl/osx/a11ywrapperradiobutton.mm +++ b/vcl/osx/a11ywrapperradiobutton.mm @@ -38,6 +38,8 @@ -(BOOL)accessibilityIsAttributeSettable:(NSString *)attribute { // Related: tdf#148453 Acquire solar mutex during native accessibility calls SolarMutexGuard aGuard; + if ( mIsDisposed ) + return NO; if ( [ attribute isEqualToString: NSAccessibilityValueAttribute ] ) { return NO; @@ -48,6 +50,8 @@ -(NSArray *)accessibilityAttributeNames { // Related: tdf#148453 Acquire solar mutex during native accessibility calls SolarMutexGuard aGuard; + if ( mIsDisposed ) + return [ NSArray array ]; // Default Attributes NSMutableArray * attributeNames = [ NSMutableArray arrayWithArray: [ super accessibilityAttributeNames ] ]; diff --git a/vcl/osx/a11ywrapperradiogroup.mm b/vcl/osx/a11ywrapperradiogroup.mm index 9768dbbb69..0896439400 100644 --- a/vcl/osx/a11ywrapperradiogroup.mm +++ b/vcl/osx/a11ywrapperradiogroup.mm @@ -30,6 +30,8 @@ -(NSArray *)accessibilityAttributeNames { // Related: tdf#148453 Acquire solar mutex during native accessibility calls SolarMutexGuard aGuard; + if ( mIsDisposed ) + return [ NSArray array ]; // Default Attributes NSMutableArray * attributeNames = [ NSMutableArray arrayWithArray: [ super accessibilityAttributeNames ] ]; diff --git a/vcl/osx/a11ywrapperrow.mm b/vcl/osx/a11ywrapperrow.mm index 0c140c82c6..a00e210ad2 100644 --- a/vcl/osx/a11ywrapperrow.mm +++ b/vcl/osx/a11ywrapperrow.mm @@ -36,6 +36,8 @@ -(NSArray *)accessibilityAttributeNames { // Related: tdf#148453 Acquire solar mutex during native accessibility calls SolarMutexGuard aGuard; + if ( mIsDisposed ) + return [ NSArray array ]; // Default Attributes NSMutableArray * attributeNames = [ NSMutableArray arrayWithArray: [ super accessibilityAttributeNames ] ]; diff --git a/vcl/osx/a11ywrapperscrollarea.mm b/vcl/osx/a11ywrapperscrollarea.mm index 22037220d4..4fa30a9f04 100644 --- a/vcl/osx/a11ywrapperscrollarea.mm +++ b/vcl/osx/a11ywrapperscrollarea.mm @@ -62,6 +62,8 @@ -(NSArray *)accessibilityAttributeNames { // Related: tdf#148453 Acquire solar mutex during native accessibility calls SolarMutexGuard aGuard; + if ( mIsDisposed ) + return [ NSArray array ]; // Default Attributes NSMutableArray * attributeNames = [ NSMutableArray arrayWithArray: [ super accessibilityAttributeNames ] ]; diff --git a/vcl/osx/a11ywrapperscrollbar.mm b/vcl/osx/a11ywrapperscrollbar.mm index 4a4612d3bb..8117e391ba 100644 --- a/vcl/osx/a11ywrapperscrollbar.mm +++ b/vcl/osx/a11ywrapperscrollbar.mm @@ -34,6 +34,8 @@ using namespace ::com::sun::star::accessibility; -(NSArray *)accessibilityAttributeNames { // Related: tdf#148453 Acquire solar mutex during native accessibility calls SolarMutexGuard aGuard; + if ( mIsDisposed ) + return [ NSArray array ]; // Default Attributes NSMutableArray * attributeNames = [ NSMutableArray arrayWithArray: [ super accessibilityAttributeNames ] ]; diff --git a/vcl/osx/a11ywrappersplitter.mm b/vcl/osx/a11ywrappersplitter.mm index 39ec496af2..993d8a0204 100644 --- a/vcl/osx/a11ywrappersplitter.mm +++ b/vcl/osx/a11ywrappersplitter.mm @@ -31,6 +31,8 @@ using namespace ::com::sun::star::accessibility; -(NSArray *)accessibilityAttributeNames { // Related: tdf#148453 Acquire solar mutex during native accessibility calls SolarMutexGuard aGuard; + if ( mIsDisposed ) + return [ NSArray array ]; // Default Attributes NSMutableArray * attributeNames = [ NSMutableArray arrayWithArray: [ super accessibilityAttributeNames ] ]; diff --git a/vcl/osx/a11ywrapperstatictext.mm b/vcl/osx/a11ywrapperstatictext.mm index 114c4179e8..317de60ee8 100644 --- a/vcl/osx/a11ywrapperstatictext.mm +++ b/vcl/osx/a11ywrapperstatictext.mm @@ -37,6 +37,8 @@ -(NSArray *)accessibilityAttributeNames { // Related: tdf#148453 Acquire solar mutex during native accessibility calls SolarMutexGuard aGuard; + if ( mIsDisposed ) + return [ NSArray array ]; // Default Attributes NSMutableArray * attributeNames = [ NSMutableArray arrayWithArray: [ super accessibilityAttributeNames ] ]; diff --git a/vcl/osx/a11ywrappertabgroup.mm b/vcl/osx/a11ywrappertabgroup.mm index 3d32ccc041..de484a5994 100644 --- a/vcl/osx/a11ywrappertabgroup.mm +++ b/vcl/osx/a11ywrappertabgroup.mm @@ -29,6 +29,8 @@ -(NSArray *)accessibilityAttributeNames { // Related: tdf#148453 Acquire solar mutex during native accessibility calls SolarMutexGuard aGuard; + if ( mIsDisposed ) + return [ NSArray array ]; // Default Attributes NSMutableArray * attributeNames = [ NSMutableArray arrayWithArray: [ super accessibilityAttributeNames ] ]; diff --git a/vcl/osx/a11ywrappertextarea.mm b/vcl/osx/a11ywrappertextarea.mm index 354030fb9a..a53550f084 100644 --- a/vcl/osx/a11ywrappertextarea.mm +++ b/vcl/osx/a11ywrappertextarea.mm @@ -29,6 +29,8 @@ -(NSArray *)accessibilityAttributeNames { // Related: tdf#148453 Acquire solar mutex during native accessibility calls SolarMutexGuard aGuard; + if ( mIsDisposed ) + return [ NSArray array ]; // Default Attributes NSMutableArray * attributeNames = [ NSMutableArray arrayWithArray: [ super accessibilityAttributeNames ] ]; diff --git a/vcl/osx/a11ywrappertoolbar.mm b/vcl/osx/a11ywrappertoolbar.mm index 28b5d01328..e2d0ec5a2a 100644 --- a/vcl/osx/a11ywrappertoolbar.mm +++ b/vcl/osx/a11ywrappertoolbar.mm @@ -29,6 +29,8 @@ -(NSArray *)accessibilityAttributeNames { // Related: tdf#148453 Acquire solar mutex during native accessibility calls SolarMutexGuard aGuard; + if ( mIsDisposed ) + return [ NSArray array ]; // Default Attributes NSMutableArray * attributeNames = [ NSMutableArray arrayWithArray: [ super accessibilityAttributeNames ] ]; diff --git a/vcl/osx/salinst.cxx b/vcl/osx/salinst.cxx index 7f755bb618..33101c8d1b 100644 --- a/vcl/osx/salinst.cxx +++ b/vcl/osx/salinst.cxx @@ -750,7 +750,22 @@ bool AquaSalInstance::AnyInput( VclInputFlags nType ) // not NSEventTypeScrollWheel. NSEvent* pCurrentEvent = [NSApp currentEvent]; if( pCurrentEvent && [pCurrentEvent type] == NSEventTypeScrollWheel ) - nEventMask &= ~NSEventMaskScrollWheel; + { + // tdf#160767 skip fix for tdf#155266 when the event hasn't changed + // When scrolling in Writer with automatic spellchecking enabled, + // the current event never changes because the fix for tdf#155266 + // causes Writer to get stuck in a loop. So, if the current event + // has not changed since the last pass through this code, skip + // the fix for tdf#155266. + static NSEvent *pLastCurrentEvent = nil; + if( pLastCurrentEvent != pCurrentEvent ) + { + if( pLastCurrentEvent ) + [pLastCurrentEvent release]; + pLastCurrentEvent = [pCurrentEvent retain]; + nEventMask &= ~NSEventMaskScrollWheel; + } + } } if( nType & VclInputFlags::KEYBOARD) diff --git a/vcl/osx/salmenu.cxx b/vcl/osx/salmenu.cxx index 6ea16a6588..800affc060 100644 --- a/vcl/osx/salmenu.cxx +++ b/vcl/osx/salmenu.cxx @@ -163,6 +163,7 @@ static void initAppMenu() pNewItem = [pAppMenu addItemWithTitle: pString action: nil keyEquivalent: @""]; + [pString release]; NSMenu *servicesMenu = [[[NSMenu alloc] initWithTitle:@"Services"] autorelease]; [pNewItem setSubmenu: servicesMenu]; [NSApp setServicesMenu: servicesMenu]; diff --git a/vcl/qt5/QtClipboard.cxx b/vcl/qt5/QtClipboard.cxx index e9eb476fb2..ea05784bbf 100644 --- a/vcl/qt5/QtClipboard.cxx +++ b/vcl/qt5/QtClipboard.cxx @@ -103,7 +103,7 @@ css::uno::Reference<css::datatransfer::XTransferable> QtClipboard::getContents() { const auto* pTrans = dynamic_cast<QtClipboardTransferable*>(m_aContents.get()); assert(pTrans); - if (pTrans && pTrans->mimeData() == pMimeData) + if (pTrans && pTrans->hasMimeData(pMimeData)) return m_aContents; } diff --git a/vcl/qt5/QtFrame.cxx b/vcl/qt5/QtFrame.cxx index 6aff814aac..1c3839a287 100644 --- a/vcl/qt5/QtFrame.cxx +++ b/vcl/qt5/QtFrame.cxx @@ -35,6 +35,7 @@ #include <QtX11Support.hxx> #endif +#include <QtCore/QLibraryInfo> #include <QtCore/QMimeData> #include <QtCore/QPoint> #include <QtCore/QSize> @@ -1339,8 +1340,17 @@ void QtFrame::ResolveWindowHandle(SystemEnvData& rData) const if (!rData.pWidget) return; assert(rData.platform != SystemEnvData::Platform::Invalid); - if (rData.platform != SystemEnvData::Platform::Wayland) + // Calling QWidget::winId() implicitly enables native windows to be used instead + // of "alien widgets" that don't have a native widget asscoiated with them, + // s. https://doc.qt.io/qt-6/qwidget.html#native-widgets-vs-alien-widgets + // Avoid native widgets with Qt 5 on Wayland and with Qt 6 altogether as they + // cause unsresponsive UI, s. tdf#122293/QTBUG-75766 and tdf#160565 + // (for qt5 xcb, they're needed for video playback) + if (rData.platform != SystemEnvData::Platform::Wayland + && QLibraryInfo::version().majorVersion() < 6) + { rData.SetWindowHandle(static_cast<QWidget*>(rData.pWidget)->winId()); + } } bool QtFrame::GetUseReducedAnimation() const { return GetQtInstance()->GetUseReducedAnimation(); } diff --git a/vcl/qt5/QtTransferable.cxx b/vcl/qt5/QtTransferable.cxx index d9e0beaa71..1aec5da278 100644 --- a/vcl/qt5/QtTransferable.cxx +++ b/vcl/qt5/QtTransferable.cxx @@ -13,6 +13,7 @@ #include <comphelper/sequence.hxx> #include <sal/log.hxx> #include <o3tl/string_view.hxx> +#include <tools/debug.hxx> #include <QtWidgets/QApplication> @@ -43,22 +44,14 @@ static bool lcl_textMimeInfo(std::u16string_view rMimeString, bool& bHaveNoChars QtTransferable::QtTransferable(const QMimeData* pMimeData) : m_pMimeData(pMimeData) - , m_bProvideUTF16FromOtherEncoding(false) { assert(pMimeData); } css::uno::Sequence<css::datatransfer::DataFlavor> SAL_CALL QtTransferable::getTransferDataFlavors() { - // it's just filled once, ever, so just try to get it without locking first - if (m_aMimeTypeSeq.hasElements()) - return m_aMimeTypeSeq; - - // better safe then sorry; preventing broken usage - // DnD should not be shared and Clipboard access runs in the GUI thread - osl::MutexGuard aGuard(m_aMutex); - if (m_aMimeTypeSeq.hasElements()) - return m_aMimeTypeSeq; + if (!m_pMimeData) + return css::uno::Sequence<css::datatransfer::DataFlavor>(); QStringList aFormatList(m_pMimeData->formats()); // we might add the UTF-16 mime text variant later @@ -101,8 +94,10 @@ css::uno::Sequence<css::datatransfer::DataFlavor> SAL_CALL QtTransferable::getTr nMimeTypeCount++; } - m_bProvideUTF16FromOtherEncoding = (bHaveNoCharset || bHaveUTF8) && !bHaveUTF16; - if (m_bProvideUTF16FromOtherEncoding) + // in case of text/plain data, but no UTF-16 encoded one, + // QtTransferable::getTransferData converts from existing encoding to UTF-16 + const bool bProvideUTF16FromOtherEncoding = (bHaveNoCharset || bHaveUTF8) && !bHaveUTF16; + if (bProvideUTF16FromOtherEncoding) { aFlavor.MimeType = "text/plain;charset=utf-16"; aFlavor.DataType = cppu::UnoType<OUString>::get(); @@ -113,8 +108,7 @@ css::uno::Sequence<css::datatransfer::DataFlavor> SAL_CALL QtTransferable::getTr aMimeTypeSeq.realloc(nMimeTypeCount); - m_aMimeTypeSeq = aMimeTypeSeq; - return m_aMimeTypeSeq; + return aMimeTypeSeq; } sal_Bool SAL_CALL @@ -135,26 +129,24 @@ css::uno::Any SAL_CALL QtTransferable::getTransferData(const css::datatransfer:: if (rFlavor.MimeType == "text/plain;charset=utf-16") { OUString aString; - if (m_bProvideUTF16FromOtherEncoding) - { - if (m_pMimeData->hasFormat("text/plain;charset=utf-8")) - { - QByteArray aByteData(m_pMimeData->data(QStringLiteral("text/plain;charset=utf-8"))); - aString = OUString::fromUtf8(reinterpret_cast<const char*>(aByteData.data())); - } - else - { - QByteArray aByteData(m_pMimeData->data(QStringLiteral("text/plain"))); - aString = OUString(reinterpret_cast<const char*>(aByteData.data()), - aByteData.size(), osl_getThreadTextEncoding()); - } - } - else + // use existing UTF-16 encoded text/plain or convert to UTF-16 as needed + if (m_pMimeData->hasFormat("text/plain;charset=utf-16")) { QByteArray aByteData(m_pMimeData->data(toQString(rFlavor.MimeType))); aString = OUString(reinterpret_cast<const sal_Unicode*>(aByteData.data()), aByteData.size() / 2); } + else if (m_pMimeData->hasFormat("text/plain;charset=utf-8")) + { + QByteArray aByteData(m_pMimeData->data(QStringLiteral("text/plain;charset=utf-8"))); + aString = OUString::fromUtf8(reinterpret_cast<const char*>(aByteData.data())); + } + else + { + QByteArray aByteData(m_pMimeData->data(QStringLiteral("text/plain"))); + aString = OUString(reinterpret_cast<const char*>(aByteData.data()), aByteData.size(), + osl_getThreadTextEncoding()); + } aAny <<= aString; } else @@ -175,11 +167,22 @@ QtClipboardTransferable::QtClipboardTransferable(const QClipboard::Mode aMode, { } -bool QtClipboardTransferable::hasInFlightChanged() const +void QtClipboardTransferable::ensureConsistencyWithSystemClipboard() +{ + const QMimeData* pCurrentClipboardData = QApplication::clipboard()->mimeData(m_aMode); + if (mimeData() != pCurrentClipboardData) + { + SAL_WARN("vcl.qt", "In flight clipboard change detected - updating mime data with current " + "clipboard contents."); + DBG_TESTSOLARMUTEX(); + setMimeData(pCurrentClipboardData); + } +} + +bool QtClipboardTransferable::hasMimeData(const QMimeData* pMimeData) const { - const bool bChanged(mimeData() != QApplication::clipboard()->mimeData(m_aMode)); - SAL_WARN_IF(bChanged, "vcl.qt", "In flight clipboard change detected - broken clipboard read!"); - return bChanged; + SolarMutexGuard aGuard; + return QtTransferable::mimeData() == pMimeData; } css::uno::Any SAL_CALL @@ -189,8 +192,8 @@ QtClipboardTransferable::getTransferData(const css::datatransfer::DataFlavor& rF auto* pSalInst(GetQtInstance()); SolarMutexGuard g; pSalInst->RunInMainThread([&, this]() { - if (!hasInFlightChanged()) - aAny = QtTransferable::getTransferData(rFlavor); + ensureConsistencyWithSystemClipboard(); + aAny = QtTransferable::getTransferData(rFlavor); }); return aAny; } @@ -202,8 +205,8 @@ css::uno::Sequence<css::datatransfer::DataFlavor> auto* pSalInst(GetQtInstance()); SolarMutexGuard g; pSalInst->RunInMainThread([&, this]() { - if (!hasInFlightChanged()) - aSeq = QtTransferable::getTransferDataFlavors(); + ensureConsistencyWithSystemClipboard(); + aSeq = QtTransferable::getTransferDataFlavors(); }); return aSeq; } @@ -215,8 +218,8 @@ QtClipboardTransferable::isDataFlavorSupported(const css::datatransfer::DataFlav auto* pSalInst(GetQtInstance()); SolarMutexGuard g; pSalInst->RunInMainThread([&, this]() { - if (!hasInFlightChanged()) - bIsSupported = QtTransferable::isDataFlavorSupported(rFlavor); + ensureConsistencyWithSystemClipboard(); + bIsSupported = QtTransferable::isDataFlavorSupported(rFlavor); }); return bIsSupported; } diff --git a/vcl/skia/gdiimpl.cxx b/vcl/skia/gdiimpl.cxx index dce3175feb..5a04a08b64 100644 --- a/vcl/skia/gdiimpl.cxx +++ b/vcl/skia/gdiimpl.cxx @@ -2174,7 +2174,7 @@ void SkiaSalGraphicsImpl::drawGenericLayout(const GenericSalLayout& layout, Colo preDraw(); auto getBoundRect = [&layout]() { - tools::Rectangle rect; + basegfx::B2DRectangle rect; layout.GetBoundRect(rect); return rect; }; diff --git a/vcl/source/app/salvtables.cxx b/vcl/source/app/salvtables.cxx index faf645fc79..8dc0edf814 100644 --- a/vcl/source/app/salvtables.cxx +++ b/vcl/source/app/salvtables.cxx @@ -6927,6 +6927,8 @@ public: virtual void set_mru_entries(const OUString&) override { assert(false && "not implemented"); } + virtual void set_max_drop_down_rows(int) override { assert(false && "not implemented"); } + virtual void set_item_menu(const OUString&, weld::Menu*) override { assert(false && "not implemented"); diff --git a/vcl/source/app/svapp.cxx b/vcl/source/app/svapp.cxx index e1e12dbc3e..71b884423a 100644 --- a/vcl/source/app/svapp.cxx +++ b/vcl/source/app/svapp.cxx @@ -103,7 +103,6 @@ vcl::KeyCode const ReservedKeys[] vcl::KeyCode(KEY_F2,KEY_SHIFT) , vcl::KeyCode(KEY_F4,KEY_MOD1) , vcl::KeyCode(KEY_F4,KEY_MOD2) , - vcl::KeyCode(KEY_F4,KEY_MOD1|KEY_MOD2) , vcl::KeyCode(KEY_F6,0) , vcl::KeyCode(KEY_F6,KEY_MOD1) , vcl::KeyCode(KEY_F6,KEY_SHIFT) , diff --git a/vcl/source/filter/igif/gifread.cxx b/vcl/source/filter/igif/gifread.cxx index 8f56edaee7..95b70568d9 100644 --- a/vcl/source/filter/igif/gifread.cxx +++ b/vcl/source/filter/igif/gifread.cxx @@ -99,7 +99,7 @@ class GIFReader : public GraphicReader sal_uInt8 nGCDisposalMethod; // 'Disposal Method' (see GIF docs) sal_uInt8 cTransIndex1; sal_uInt8 cNonTransIndex1; - bool bEnhance; + sal_uLong nPaletteSize; void ReadPaletteEntries( BitmapPalette* pPal, sal_uLong nCount ); void ClearImageExtensions(); @@ -157,7 +157,7 @@ GIFReader::GIFReader( SvStream& rStm ) , nGCTransparentIndex ( 0 ) , cTransIndex1 ( 0 ) , cNonTransIndex1 ( 0 ) - , bEnhance( false ) + , nPaletteSize( 0 ) { maUpperName = "SVIGIF"; aSrcBuf.resize(256); // Memory buffer for ReadNextBlock @@ -328,12 +328,7 @@ void GIFReader::ReadPaletteEntries( BitmapPalette* pPal, sal_uLong nCount ) (*pPal)[ 254UL ] = COL_BLACK; } - // tdf#157793 limit tdf#157635 fix to only larger palettes - // I don't know why, but the fix for tdf#157635 causes - // images with a palette of 16 entries to be inverted. - // Also, fix tdf#158047 by allowing the tdf#157635 fix for - // palettes with 64 entries. - bEnhance = (nCount > 16); + nPaletteSize = nCount; } bool GIFReader::ReadExtension() @@ -674,16 +669,25 @@ void GIFReader::CreateNewBitmaps() aAlphaMask.Invert(); // convert from transparency to alpha aAnimationFrame.maBitmapEx = BitmapEx( aBmp8, aAlphaMask ); } - else + else if( nPaletteSize > 2 ) { - // tdf#157576 and tdf#157635 mask out black pixels + // tdf#160690 set an opaque alpha mask for non-transparent frames // Due to the switch from transparency to alpha in commit - // 81994cb2b8b32453a92bcb011830fcb884f22ff3, mask out black - // pixels in bitmap. - if (bEnhance) - aAnimationFrame.maBitmapEx = BitmapEx( aBmp8, aBmp8 ); - else - aAnimationFrame.maBitmapEx = BitmapEx( aBmp8 ); + // 81994cb2b8b32453a92bcb011830fcb884f22ff3, an empty alpha mask + // is treated as a completely transparent bitmap. So revert all + // of the previous commits for tdf#157576, tdf#157635, and tdf#157793 + // and create a completely opaque bitmap instead. + // Note: this fix also fixes tdf#157576, tdf#157635, and tdf#157793. + AlphaMask aAlphaMask(aBmp8.GetSizePixel()); + aAnimationFrame.maBitmapEx = BitmapEx( aBmp8, aAlphaMask ); + } + else + { + // Don't apply the fix for tdf#160690 as it will cause 1 bit bitmaps + // in Word documents like the following test document to fail to be + // parsed correctly: + // sw/qa/extras/tiledrendering/data/tdf159626_yellowPatternFill.docx + aAnimationFrame.maBitmapEx = BitmapEx( aBmp8 ); } aAnimationFrame.maPositionPixel = Point( nImagePosX, nImagePosY ); diff --git a/vcl/source/gdi/pdfwriter_impl.cxx b/vcl/source/gdi/pdfwriter_impl.cxx index ff7383d7be..16b0b5e235 100644 --- a/vcl/source/gdi/pdfwriter_impl.cxx +++ b/vcl/source/gdi/pdfwriter_impl.cxx @@ -2746,15 +2746,11 @@ bool PDFWriterImpl::emitType3Font(const vcl::font::PhysicalFontFace* pFace, appendDouble(aRect.GetWidth() * fScale, aContents); aContents.append(" 0 0 "); appendDouble(aRect.GetHeight() * fScale, aContents); - aContents.append( - + " " - + OString::number(aRect.getX()) - + " " - + OString::number(aRect.getY()) - + " cm " - "/Im" - + OString::number(nObject) - + " Do Q\n"); + aContents.append(" "); + appendDouble(aRect.getX() * fScale, aContents); + aContents.append(" "); + appendDouble(aRect.getY() * fScale, aContents); + aContents.append(" cm /Im" + OString::number(nObject) + " Do Q\n"); } const auto& rOutline = rGlyph.getOutline(); diff --git a/vcl/source/gdi/sallayout.cxx b/vcl/source/gdi/sallayout.cxx index 28138c3f61..3b1279dd1f 100644 --- a/vcl/source/gdi/sallayout.cxx +++ b/vcl/source/gdi/sallayout.cxx @@ -220,11 +220,10 @@ static double trimInsignificant(double n) return std::abs(n) >= 0x1p53 ? n : std::round(n * 1e5) / 1e5; } -bool SalLayout::GetBoundRect(tools::Rectangle& rRect) const +bool SalLayout::GetBoundRect(basegfx::B2DRectangle& rRect) const { bool bRet = false; - - basegfx::B2DRectangle aUnion; + rRect.reset(); basegfx::B2DRectangle aRectangle; basegfx::B2DPoint aPos; @@ -240,28 +239,28 @@ bool SalLayout::GetBoundRect(tools::Rectangle& rRect) const { aRectangle.transform(basegfx::utils::createTranslateB2DHomMatrix(aPos)); // merge rectangle - aUnion.expand(aRectangle); + rRect.expand(aRectangle); } bRet = true; } } - if (aUnion.isEmpty()) - { - rRect = {}; - } - else - { - double l = rtl::math::approxFloor(trimInsignificant(aUnion.getMinX())), - t = rtl::math::approxFloor(trimInsignificant(aUnion.getMinY())), - r = rtl::math::approxCeil(trimInsignificant(aUnion.getMaxX())), - b = rtl::math::approxCeil(trimInsignificant(aUnion.getMaxY())); - assert(std::isfinite(l) && std::isfinite(t) && std::isfinite(r) && std::isfinite(b)); - rRect = tools::Rectangle(l, t, r, b); - } return bRet; } +tools::Rectangle SalLayout::BoundRect2Rectangle(basegfx::B2DRectangle& rRect) +{ + if (rRect.isEmpty()) + return {}; + + double l = rtl::math::approxFloor(trimInsignificant(rRect.getMinX())), + t = rtl::math::approxFloor(trimInsignificant(rRect.getMinY())), + r = rtl::math::approxCeil(trimInsignificant(rRect.getMaxX())), + b = rtl::math::approxCeil(trimInsignificant(rRect.getMaxY())); + assert(std::isfinite(l) && std::isfinite(t) && std::isfinite(r) && std::isfinite(b)); + return tools::Rectangle(l, t, r, b); +} + SalLayoutGlyphs SalLayout::GetGlyphs() const { return SalLayoutGlyphs(); // invalid diff --git a/vcl/source/helper/idletask.cxx b/vcl/source/helper/idletask.cxx index 7df0514912..2865d8d036 100644 --- a/vcl/source/helper/idletask.cxx +++ b/vcl/source/helper/idletask.cxx @@ -14,8 +14,8 @@ IdleTask::IdleTask() : flag(false) { - //setting the Priority of Idle task to LOW, LOWEST - maIdle.SetPriority(TaskPriority::LOWEST); + //setting the Priority of Idle task to TOOLKIT_DEBUG + maIdle.SetPriority(TaskPriority::TOOLKIT_DEBUG); //set idle for callback maIdle.SetInvokeHandler(LINK(this, IdleTask, FlipFlag)); //starting the idle diff --git a/vcl/source/outdev/map.cxx b/vcl/source/outdev/map.cxx index 23c68a2385..8707805eb1 100644 --- a/vcl/source/outdev/map.cxx +++ b/vcl/source/outdev/map.cxx @@ -1217,6 +1217,14 @@ basegfx::B2DPolyPolygon OutputDevice::PixelToLogic( const basegfx::B2DPolyPolygo return aTransformedPoly; } +basegfx::B2DRectangle OutputDevice::PixelToLogic(const basegfx::B2DRectangle& rDeviceRect) const +{ + basegfx::B2DRectangle aTransformedRect = rDeviceRect; + const basegfx::B2DHomMatrix& rTransformationMatrix = GetInverseViewTransformation(); + aTransformedRect.transform(rTransformationMatrix); + return aTransformedRect; +} + vcl::Region OutputDevice::PixelToLogic( const vcl::Region& rDeviceRegion ) const { diff --git a/vcl/source/outdev/text.cxx b/vcl/source/outdev/text.cxx index 1b40a1b2de..16fdf7b073 100644 --- a/vcl/source/outdev/text.cxx +++ b/vcl/source/outdev/text.cxx @@ -21,6 +21,7 @@ #include <sal/log.hxx> #include <basegfx/matrix/b2dhommatrix.hxx> +#include <basegfx/matrix/b2dhommatrixtools.hxx> #include <tools/lineend.hxx> #include <tools/debug.hxx> #include <unotools/configmgr.hxx> @@ -214,7 +215,11 @@ bool OutputDevice::ImplDrawRotateText( SalLayout& rSalLayout ) tools::Rectangle aBoundRect; rSalLayout.DrawBase() = basegfx::B2DPoint( 0, 0 ); rSalLayout.DrawOffset() = Point( 0, 0 ); - if (!rSalLayout.GetBoundRect(aBoundRect)) + if (basegfx::B2DRectangle r; rSalLayout.GetBoundRect(r)) + { + aBoundRect = SalLayout::BoundRect2Rectangle(r); + } + else { // guess vertical text extents if GetBoundRect failed double nRight = rSalLayout.GetTextWidth(); @@ -1922,8 +1927,21 @@ bool OutputDevice::GetTextBoundRect( tools::Rectangle& rRect, std::span<const sal_Bool> pKashidaAry, const SalLayoutGlyphs* pGlyphs ) const { + basegfx::B2DRectangle aRect; + bool bRet = GetTextBoundRect(aRect, rStr, nBase, nIndex, nLen, nLayoutWidth, pDXAry, + pKashidaAry, pGlyphs); + rRect = SalLayout::BoundRect2Rectangle(aRect); + return bRet; +} + +bool OutputDevice::GetTextBoundRect(basegfx::B2DRectangle& rRect, const OUString& rStr, + sal_Int32 nBase, sal_Int32 nIndex, sal_Int32 nLen, + sal_uLong nLayoutWidth, KernArraySpan pDXAry, + std::span<const sal_Bool> pKashidaAry, + const SalLayoutGlyphs* pGlyphs) const +{ bool bRet = false; - rRect.SetEmpty(); + rRect.reset(); std::unique_ptr<SalLayout> pSalLayout; const Point aPoint; @@ -1947,18 +1965,22 @@ bool OutputDevice::GetTextBoundRect( tools::Rectangle& rRect, nullptr, pGlyphs); if( pSalLayout ) { - tools::Rectangle aPixelRect; + basegfx::B2DRectangle aPixelRect; bRet = pSalLayout->GetBoundRect(aPixelRect); if( bRet ) { - Point aRotatedOfs( mnTextOffX, mnTextOffY ); basegfx::B2DPoint aPos = pSalLayout->GetDrawPosition(basegfx::B2DPoint(nXOffset, 0)); - aRotatedOfs -= Point(aPos.getX(), aPos.getY()); - aPixelRect += aRotatedOfs; + auto m = basegfx::utils::createTranslateB2DHomMatrix(mnTextOffX - aPos.getX(), + mnTextOffY - aPos.getY()); + aPixelRect.transform(m); rRect = PixelToLogic( aPixelRect ); - if( mbMap ) - rRect += Point( maMapRes.mnMapOfsX, maMapRes.mnMapOfsY ); + if (mbMap) + { + m = basegfx::utils::createTranslateB2DHomMatrix(maMapRes.mnMapOfsX, + maMapRes.mnMapOfsY); + rRect.transform(m); + } } } diff --git a/vcl/unx/gtk3/gtkinst.cxx b/vcl/unx/gtk3/gtkinst.cxx index a899fc16c6..6a06947d4c 100644 --- a/vcl/unx/gtk3/gtkinst.cxx +++ b/vcl/unx/gtk3/gtkinst.cxx @@ -21034,6 +21034,11 @@ public: #endif } + virtual void set_max_drop_down_rows(int) override + { + SAL_WARN( "vcl.gtk", "set_max_drop_down_rows unimplemented"); + } + virtual ~GtkInstanceComboBox() override { // m_xCustomMenuButtonHelper.reset(); @@ -21114,6 +21119,7 @@ private: gint m_nPrePopupCursorPos; int m_nMRUCount; int m_nMaxMRUCount; + int m_nMaxDropdownRows; static gboolean idleAutoComplete(gpointer widget) { @@ -21236,7 +21242,7 @@ private: { const StyleSettings& rSettings = Application::GetSettings().GetStyleSettings(); - int nMaxRows = rSettings.GetListBoxMaximumLineCount(); + int nMaxRows = m_nMaxDropdownRows == -1 ? rSettings.GetListBoxMaximumLineCount() : m_nMaxDropdownRows; bool bAddScrollWidth = false; int nRows = get_count_including_mru(); if (nMaxRows < nRows) @@ -22154,6 +22160,7 @@ public: , m_nPrePopupCursorPos(-1) , m_nMRUCount(0) , m_nMaxMRUCount(0) + , m_nMaxDropdownRows(-1) { int nActive = gtk_combo_box_get_active(m_pComboBox); @@ -22838,6 +22845,11 @@ public: return nWidth; } + virtual void set_max_drop_down_rows(int nMaxRows) override + { + m_nMaxDropdownRows = nMaxRows; + } + virtual ~GtkInstanceComboBox() override { m_xCustomMenuButtonHelper.reset(); @@ -23223,6 +23235,8 @@ public: return 0; } + virtual void set_max_drop_down_rows(int) override { assert(false && "not implemented"); } + virtual ~GtkInstanceEntryTreeView() override { if (m_nAutoCompleteIdleId) diff --git a/vcl/unx/gtk3/hudawareness.cxx b/vcl/unx/gtk3/hudawareness.cxx index ebcbaf747f..749e3d5c0d 100644 --- a/vcl/unx/gtk3/hudawareness.cxx +++ b/vcl/unx/gtk3/hudawareness.cxx @@ -88,7 +88,7 @@ hud_awareness_register (GDBusConnection *connection, if (object_id == 0) { - g_free (handle); + // note: tdf#161073 handle is expected to be freed by g_dbus_connection_register_object on failure return 0; } diff --git a/vcl/win/gdi/DWriteTextRenderer.cxx b/vcl/win/gdi/DWriteTextRenderer.cxx index 3d3dac83c6..82508061b6 100644 --- a/vcl/win/gdi/DWriteTextRenderer.cxx +++ b/vcl/win/gdi/DWriteTextRenderer.cxx @@ -225,8 +225,15 @@ bool D2DWriteTextOutRenderer::performRender(GenericSalLayout const & rLayout, Sa if (!pFontFace) return false; - tools::Rectangle bounds; - bool succeeded = rLayout.GetBoundRect(bounds); + auto [succeeded, bounds] = [&rLayout]() + { + basegfx::B2DRectangle r; + bool result = rLayout.GetBoundRect(r); + if (result) + r.grow(1); // plus 1 pixel to the tight range + return std::make_pair(result, SalLayout::BoundRect2Rectangle(r)); + }(); + if (succeeded) { hr = BindDC(hDC, bounds); // Update the bounding rect. |