if (comphelper::LibreOfficeKit::isActive())
{ // In the future we might send the payload as well.
SfxLokHelper::notifyAllViews(LOK_CALLBACK_CLIPBOARD_CHANGED, ""_ostr);
}
}
void SAL_CALL SfxClipboardChangeListener::disposing( const lang::EventObject& /*rEventObject*/ )
{ // Either clipboard or ViewShell is going to be destroyed -> no interest in listening anymore
uno::Reference< lang::XComponent > xCtrl( m_xCtrl );
uno::Reference< datatransfer::clipboard::XClipboardNotifier > xNotify( m_xClpbrdNtfr );
uno::Reference< datatransfer::clipboard::XClipboardListener > xThis( static_cast< datatransfer::clipboard::XClipboardListener* >( this )); if ( xCtrl.is() )
xCtrl->removeEventListener( uno::Reference < lang::XEventListener > ( static_cast < lang::XEventListener* >( this ))); if ( xNotify.is() )
xNotify->removeClipboardListener( xThis );
// Make asynchronous call to avoid locking SolarMutex which is the // root for many deadlocks, especially in conjunction with the "Windows" // based single thread apartment clipboard code!
AsyncExecuteInfo* pInfo = new AsyncExecuteInfo( ASYNCEXECUTE_CMD_DISPOSING, this ); if (!Application::PostUserEvent( LINK( nullptr, SfxClipboardChangeListener, AsyncExecuteHdl_Impl ), pInfo )) delete pInfo;
}
void SAL_CALL SfxClipboardChangeListener::changedContents( const datatransfer::clipboard::ClipboardEvent& )
{ // Make asynchronous call to avoid locking SolarMutex which is the // root for many deadlocks, especially in conjunction with the "Windows" // based single thread apartment clipboard code!
AsyncExecuteInfo* pInfo = new AsyncExecuteInfo( ASYNCEXECUTE_CMD_CHANGEDCONTENTS, this); if (!Application::PostUserEvent( LINK( nullptr, SfxClipboardChangeListener, AsyncExecuteHdl_Impl ), pInfo )) delete pInfo;
}
// Put in rAncestorList all ancestors of xTable up to xAncestorTable or // up to the first not-a-table ancestor if xAncestorTable is not an ancestor. // xTable is included in the list, xAncestorTable is not included. // The list is ordered from the ancient ancestor to xTable. // Return true if xAncestorTable is an ancestor of xTable. bool getAncestorList(XAccessibleTableList& rAncestorList, const uno::Reference<accessibility::XAccessibleTable>& xTable, const uno::Reference<accessibility::XAccessibleTable>& xAncestorTable = uno::Reference<accessibility::XAccessibleTable>())
{
uno::Reference<accessibility::XAccessibleTable> xCurrentTable = xTable; while (xCurrentTable.is() && xCurrentTable != xAncestorTable)
{
rAncestorList.push_front(xCurrentTable);
if (stateSet == 0) return"INVALID";
::sal_Int64 state = 1;
std::string s; for (int i = 0; i < 35; ++i)
{ if (stateSet & state)
{
s += states[i];
s += "|";
}
state <<= 1;
} return s;
}
// notifyEditingInSelectionState // Used for notifying when editing becomes active/disabled for a shape // bParagraph: should we append currently focused paragraph ? // The problem is that the initially focused paragraph could not be the one user has clicked on, // when there are more than a single paragraph. // So in some case sending the focused paragraph could be misleading. void LOKDocumentFocusListener::notifyEditingInSelectionState(bool bParagraph)
{
aboutView("LOKDocumentFocusListener::notifyEditingInSelectionState", this, m_pViewShell);
/// notifyFocusedParagraphChanged // // Notify content, caret position and text selection start/end for the focused paragraph // in current view. // For focused we don't mean to be necessarily the currently focused accessibility node. // It's enough that the caret is present in the paragraph (position != -1). // In fact each view has its own accessibility node per each text paragraph. // Anyway there can be only one focused accessibility node at time. // So when text changes are performed in one view, both accessibility nodes emit // a text changed event, anyway only the accessibility node belonging to the view // where the text change has occurred is the focused one. // // force: when true update the clipboard content even if client is composing. // // Usually when editing on the client involves composing the clipboard area updating // is skipped until the composition is over. // On the contrary the composition would be aborted, making dictation not possible. // Anyway when the text change has been performed by another view we are in due // to update the clipboard content even if the user is in the middle of a composition. void LOKDocumentFocusListener::notifyFocusedParagraphChanged(bool force)
{
aboutView("LOKDocumentFocusListener::notifyFocusedParagraphChanged", this, m_pViewShell);
std::string aPayload;
paragraphPropertiesToJson(aPayload, force); if (m_pViewShell)
{
aboutParagraph("LOKDocumentFocusListener::notifyFocusedParagraphChanged",
m_sFocusedParagraph, m_nCaretPosition,
m_nSelectionStart, m_nSelectionEnd, m_nListPrefixLength, force);
void LOKDocumentFocusListener::disposing( const lang::EventObject& aEvent )
{ // Unref the object here, but do not remove as listener since the object // might no longer be in a state that safely allows this. if( aEvent.Source.is() )
m_aRefList.erase(aEvent.Source);
bool bNotify = false; // If caret is present inside the paragraph (pos != -1), it means that paragraph has focus in the current view.
sal_Int32 nCaretPosition = xAccText->getCaretPosition(); if (nCaretPosition >= 0)
{
OUString sText = xAccText->getText();
m_nCaretPosition = nCaretPosition;
m_nSelectionStart = xAccText->getSelectionStart();
m_nSelectionEnd = xAccText->getSelectionEnd();
m_nListPrefixLength = getListPrefixSize(xAccText);
// Inside a text shape when there is no selection, selection-start and selection-end are // set to current caret position instead of -1. Moreover, inside a text shape pressing // delete or backspace with an empty selection really deletes text and not only the empty // selection as it occurs in a text paragraph in Writer. // So whenever selection-start == selection-end, and we are inside a shape we need // to set these parameters to -1 in order to have the client to handle delete and // backspace properly. if (m_nSelectionStart == m_nSelectionEnd && m_nSelectionStart != -1)
{
uno::Reference<accessibility::XAccessibleContext> xContext(xAccText, uno::UNO_QUERY);
sal_Int16 nParentRole = getParentRole(xContext); if (nParentRole == accessibility::AccessibleRole::SHAPE ||
nParentRole == accessibility::AccessibleRole::TEXT_FRAME) // spreadsheet cell editing
m_nSelectionStart = m_nSelectionEnd = -1;
}
// In case only caret position or text selection are different we can rely on specific events. if (m_sFocusedParagraph != sText)
{
m_sFocusedParagraph = sText;
bNotify = true;
}
} else
{
SAL_WARN("lok.a11y", "LOKDocumentFocusListener::updateParagraphInfo: skipped since no caret is present");
}
// For a presentation document when an accessible event of type SELECTION_CHANGED_XXX occurs // the selected (or unselected) object is put in NewValue, instead for a text document // the selected object is put in Source. // The following function helps to retrieve the selected object independently on where it has been put.
uno::Reference< accessibility::XAccessible >
LOKDocumentFocusListener::getSelectedObject(const accessibility::AccessibleEventObject& aEvent) const
{
uno::Reference< accessibility::XAccessible > xSelectedObject; if (isText(m_nDocumentType))
{
xSelectedObject.set(aEvent.Source, uno::UNO_QUERY);
} else
{
aEvent.NewValue >>= xSelectedObject;
} return xSelectedObject;
}
void LOKDocumentFocusListener::onShapeSelectionChanged( const uno::Reference<accessibility::XAccessible>& xSelectedObject, const OUString& sAction)
{ // when a shape is selected or unselected we could need to notify that text content editing // is no more active, that allows on the client side to prevent default input.
resetParagraphInfo(); if (m_bIsEditingInSelection)
{
m_bIsEditingInSelection = false;
notifyEditingInSelectionState();
}
notifySelectionChanged(xSelectedObject, sAction);
}
if (m_xLastTable.is())
{ if (xTable != m_xLastTable)
{ // do we get in one or more nested tables ? // check if xTable is a descendant of m_xLastTable
XAccessibleTableList newTableAncestorList; bool isLastAncestorOfNew = getAncestorList(newTableAncestorList, xTable, m_xLastTable); bool isNewAncestorOfLast = false; if (!isLastAncestorOfNew)
{ // do we get out of one or more nested tables ? // check if m_xLastTable is a descendant of xTable
XAccessibleTableList lastTableAncestorList;
isNewAncestorOfLast = getAncestorList(lastTableAncestorList, m_xLastTable, xTable); // we have to notify "out of table" for all m_xLastTable ancestors up to xTable // or the first not-a-table ancestor
nOutCount = lastTableAncestorList.size();
} if (isLastAncestorOfNew || !isNewAncestorOfLast)
{ // we have to notify row/col count for all xTable ancestors starting from the ancestor // which is a child of m_xLastTable (isLastAncestorOfNew) or the first not-a-table ancestor for (constauto& ancestor: newTableAncestorList)
{
TableSizeType aTableSize{ancestor->getAccessibleRowCount(),
ancestor->getAccessibleColumnCount()};
aInList.push_back(aTableSize);
}
}
}
} else
{ // cursor was not inside any table and gets inside one or more tables // we have to notify row/col count for all xTable ancestors starting from first not-a-table ancestor
XAccessibleTableList newTableAncestorList;
getAncestorList(newTableAncestorList, xTable); for (constauto& ancestor: newTableAncestorList)
{
TableSizeType aTableSize{ancestor->getAccessibleRowCount(),
ancestor->getAccessibleColumnCount()};
aInList.push_back(aTableSize);
}
}
// we have to notify current row/col of xTable and related row/col span
sal_Int32 nRow = xTable->getAccessibleRow(nChildIndex);
sal_Int32 nCol = xTable->getAccessibleColumn(nChildIndex);
sal_Int32 nRowSpan = xTable->getAccessibleRowExtentAt(nRow, nCol);
sal_Int32 nColSpan = xTable->getAccessibleColumnExtentAt(nRow, nCol);
// check validity
uno::Reference< XAccessible > xAccessibleObject = getAccessible(aEvent); if (!xAccessibleObject.is()) return;
uno::Reference<XAccessibleContext> xContext(aEvent.Source, uno::UNO_QUERY); if (!xContext) return;
sal_Int16 nRole = xContext->getAccessibleRole();
if (nRole == AccessibleRole::PARAGRAPH)
{
uno::Reference<XAccessibleText> xAccText(xAccessibleObject, uno::UNO_QUERY); if (!xAccText.is()) return;
switch (nState)
{ case AccessibleStateType::ACTIVE:
{ if (!m_bIsEditingInSelection && hasToBeActiveForEditing(getParentRole(xContext)))
{
m_bIsEditingInSelection = true;
} break;
} case AccessibleStateType::FOCUSED:
{ if (m_bIsEditingInSelection && m_xSelectedObject.is())
{
updateParagraphInfo(xAccText, true, "STATE_CHANGED: FOCUSED");
notifyEditingInSelectionState(getAccessibleSiblingCount(xContext) == 0);
notifyFocusedParagraphChanged(true); // we clear selected object so when editing is over but shape is // still selected, the selection event is notified the same to the client
m_xSelectedObject.clear(); return;
} if (isText(m_nDocumentType))
{ // check if we are inside a table: in case notify table and current cell info bool isInsideTable = false;
uno::Reference<XAccessibleTable> xTable;
sal_Int64 nChildIndex = 0;
lookForParentTable(xContext, xTable, nChildIndex); if (xTable.is())
{
onFocusedParagraphInWriterTable(xTable, nChildIndex, xAccText);
isInsideTable = true;
} // paragraph is not inside any table if (!isInsideTable)
{ if (m_xLastTable.is())
{ // we get out one or more tables // we have to notify "out of table" for all m_xLastTable ancestors // up to the first not-a-table ancestor
XAccessibleTableList lastTableAncestorList;
getAncestorList(lastTableAncestorList, m_xLastTable);
sal_Int32 nOutCount = lastTableAncestorList.size(); // no more inside a table
m_xLastTable.clear(); // notify
std::vector<TableSizeType> aInList;
updateParagraphInfo(xAccText, false, "STATE_CHANGED: FOCUSED");
notifyFocusedCellChanged(nOutCount, aInList, -1, -1, 1, 1);
} else
{
updateAndNotifyParagraph(xAccText, false, "STATE_CHANGED: FOCUSED");
}
}
} elseif (isSpreadsheet(m_nDocumentType))
{ if (m_bIsEditingCell)
{ if (!hasState(aEvent, AccessibleStateType::ACTIVE))
{
SAL_WARN("lok.a11y", "LOKDocumentFocusListener::notifyEvent: FOCUSED: " "cell not ACTIVE for editing yet"); return;
} elseif (m_xSelectedObject.is())
{
updateParagraphInfo(xAccText, true, "STATE_CHANGED: ACTIVE");
notifyEditingInSelectionState(getAccessibleSiblingCount(xContext) == 0);
notifyFocusedParagraphChanged(true);
m_xSelectedObject.clear(); return;
}
if (nNewPos >= 0)
{
SAL_INFO("lok.a11y", "LOKDocumentFocusListener::notifyEvent: CARET_CHANGED: " "new pos: " << nNewPos << ", nOldPos: " << nOldPos);
uno::Reference<XAccessibleText> xAccText(getAccessible(aEvent), uno::UNO_QUERY); if (xAccText.is())
{
m_nCaretPosition = nNewPos; // Let's say we are in the following case: 'Hello wor|ld', // where '|' is the cursor position for the current view. // Suppose that in another view it's typed <enter> soon before 'world'. // Now the new paragraph content and caret position is: 'wor|ld'. // Anyway no new paragraph focused event is emitted for current view. // Only a new caret position event is emitted. // So we could need to notify a new focused paragraph changed message. if (!isFocused(aEvent))
{ if (updateParagraphInfo(xAccText, false, "CARET_CHANGED"))
notifyFocusedParagraphChanged(true);
} else
{
notifyCaretChanged();
}
aboutParagraph("LOKDocumentFocusListener::notifyEvent: CARET_CHANGED", xAccText);
}
} break;
} case AccessibleEventId::TEXT_CHANGED:
{
TextSegment aDeletedText;
TextSegment aInsertedText;
// When the change has been performed in another view we need to force // paragraph content updating on the client, even if current editing involves composing. // We make a guess that if the paragraph accessibility node is not focused, // it means that the text change has been performed in another view.
updateAndNotifyParagraph(xAccText, !isFocused(aEvent), "TEXT_CHANGED");
break;
} case AccessibleEventId::TEXT_SELECTION_CHANGED:
{ if (!isFocused(aEvent))
{
SAL_WARN("lok.a11y", "LOKDocumentFocusListener::notifyEvent: TEXT_SELECTION_CHANGED: " "skip non focused paragraph"); return;
}
uno::Reference<XAccessibleText> xAccText(getAccessible(aEvent), uno::UNO_QUERY); if (xAccText.is())
{ // We send a message to client also when start/end are -1, in this way the client knows // if a text selection object exists or not. That's needed because of the odd behavior // occurring when <backspace>/<delete> are hit and a text selection is empty, // but it still exists. // Such keys delete the empty selection instead of the previous/next char.
updateParagraphInfo(xAccText, false, "TEXT_SELECTION_CHANGED");
if (!xBroadcaster.is()) return;
SAL_INFO("lok.a11y", "LOKDocumentFocusListener::attachRecursive(3) #2: xBroadcaster.is()"); // If not already done, add the broadcaster to the list and attach as listener. const uno::Reference< uno::XInterface >& xInterface = xBroadcaster; if( m_aRefList.insert(xInterface).second )
{
SAL_INFO("lok.a11y", "LOKDocumentFocusListener::attachRecursive(3) #3: m_aRefList.insert(xInterface).second");
xBroadcaster->addAccessibleEventListener(static_cast< accessibility::XAccessibleEventListener *>(this));
if (isDocument(xContext->getAccessibleRole()))
{
m_nDocumentType = xContext->getAccessibleRole();
}
if (!(nStateSet & accessibility::AccessibleStateType::MANAGES_DESCENDANTS))
{ if ((nStateSet & accessibility::AccessibleStateType::SELECTED) &&
selectionHasToBeNotified(xContext))
{
uno::Reference< accessibility::XAccessible > xAccObj(xContext, uno::UNO_QUERY);
onShapeSelectionChanged(xAccObj, u"create"_ustr);
}
for( sal_Int64 n = 0; n < nmax; n++ )
{
uno::Reference< accessibility::XAccessible > xChild( xContext->getAccessibleChild( n ) );
if( xChild.is() )
attachRecursive(xChild);
}
} else
{ // Usually, when the document is loaded, a CARET_CHANGED accessibility event is automatically emitted // for the first paragraph. That allows to notify the paragraph content to the client, even if no input // event occurred yet. However, when switching to a11y enabled in the client and in Cypress tests // no accessibility event is automatically emitted until some input event occurs. // So we use the following workaround to notify the content of the focused paragraph, // without waiting for an input event. // Here we update the paragraph info related to the focused paragraph, // later when afterCallbackRegistered is executed we notify the paragraph content.
sal_Int64 nChildCount = xContext->getAccessibleChildCount(); if (nChildCount > 0 && nChildCount < 10)
{ for (sal_Int64 n = 0; n < nChildCount; ++n)
{
uno::Reference< accessibility::XAccessible > xChild(xContext->getAccessibleChild(n)); if (xChild.is())
{
uno::Reference<css::accessibility::XAccessibleText> xAccText(xChild, uno::UNO_QUERY); if (xAccText.is())
{
sal_Int32 nPos = xAccText->getCaretPosition(); if (nPos >= 0)
{
attachRecursive(xChild);
updateParagraphInfo(xAccText, false, "LOKDocumentFocusListener::attachRecursive(3)"); break;
}
}
}
}
}
}
}
}
/** search for an internal typename, which map to the current app module andmapalsotoa"family"offileformatsase.g.PDF/MSDoc/OOoDoc.
*/ enum ETypeFamily
{
E_MS_DOC,
E_OOO_DOC
};
case SID_MAIL_SENDDOCASMS: case SID_MAIL_SENDDOCASOOO: case SID_MAIL_SENDDOCASPDF: case SID_MAIL_SENDDOC: case SID_MAIL_SENDDOCASFORMAT:
{
SfxObjectShell* pDoc = GetObjectShell(); if (!pDoc) break;
pDoc->QueryHiddenInformation(HiddenWarningFact::WhenSaving);
SfxMailModel aModel;
OUString aDocType;
if ( xFrame.is() )
{
css::uno::Reference< css::frame::XController > xController = xFrame->getController(); if ( xController.is() )
xModel = xController->getModel();
}
// We need at least a valid module name and model reference
css::uno::Reference< css::frame::XStorable > xStorable( xModel, css::uno::UNO_QUERY ); if ( xModel.is() && xStorable.is() )
{
OUString aFilterName;
OUString aTypeName( u"generic_HTML"_ustr );
OUString aFileName;
sal_Int32 nFilterFlags = 0x00000002; // export
aFilterName = impl_retrieveFilterNameFromTypeAndModule( xContainerQuery, aTypeName, aModule, nFilterFlags ); if ( aFilterName.isEmpty() )
{ // Draw/Impress uses a different type. 2nd chance try to use alternative type name
aFilterName = impl_retrieveFilterNameFromTypeAndModule(
xContainerQuery, u"graphic_HTML"_ustr, aModule, nFilterFlags );
}
// No filter found => error // No type and no location => error if ( aFilterName.isEmpty() || aTypeName.isEmpty())
{
rReq.Done(); return;
}
// Use provided save file name. If empty determine file name if ( !bHasLocation )
{ // Create a default file name with the correct extension
aFileName = "webpreview";
} else
{ // Determine file name from model
INetURLObject aFObj( xStorable->getLocation() );
aFileName = aFObj.getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::DecodeMechanism::NONE );
}
// Creates a temporary directory to store our predefined file into it (for the // flatpak case, create it in XDG_CACHE_HOME instead of /tmp for technical reasons, // so that it can be accessed by the browser running outside the sandbox):
OUString * parent = nullptr; if (flatpak::isFlatpak() && !flatpak::createTemporaryHtmlDirectory(&parent))
{
SAL_WARN("sfx.view", "cannot create Flatpak html temp dir");
}
case SID_BLUETOOTH_SENDDOC: case SID_MAIL_SENDDOC: case SID_MAIL_SENDDOCASFORMAT: case SID_MAIL_SENDDOCASMS: case SID_MAIL_SENDDOCASOOO: case SID_MAIL_SENDDOCASPDF:
{ #if HAVE_FEATURE_MACOSX_SANDBOX
rSet.DisableItem(nSID); #endif if (pSh && pSh->isExportLocked())
rSet.DisableItem(nSID); break;
} case SID_WEBHTML:
{ if (pSh && pSh->isExportLocked())
rSet.DisableItem(nSID); break;
} // Printer functions case SID_PRINTDOC: case SID_PRINTDOCDIRECT: case SID_SETUPPRINTER: case SID_PRINTER_NAME:
{ if (Application::GetSettings().GetMiscSettings().GetDisablePrinting()
|| (pSh && pSh->isPrintLocked()))
{
rSet.DisableItem(nSID); break;
}
SfxPrinter *pPrinter = GetPrinter();
if ( SID_PRINTDOCDIRECT == nSID )
{
OUString aPrinterName; if ( pPrinter != nullptr )
aPrinterName = pPrinter->GetName(); else
{ // tdf#109149 don't poll the Default Printer Name on every query. // We are queried on every change, so on every // keystroke, and we are only using this to fill in the // printername inside the label of "Print Directly (printer-name)" // On Printer::GetDefaultPrinterName() is implemented with // GetDefaultPrinter so don't call this excessively. 5 mins // seems a reasonable refresh time.
std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now();
std::chrono::minutes five_mins(5); if (now > pImpl->m_nDefaultPrinterNameFetchTime + five_mins)
{
pImpl->m_sDefaultPrinterName = Printer::GetDefaultPrinterName();
pImpl->m_nDefaultPrinterNameFetchTime = now;
}
aPrinterName = pImpl->m_sDefaultPrinterName;
} if ( !aPrinterName.isEmpty() )
{
uno::Reference < frame::XFrame > xFrame( rFrame.GetFrame().GetFrameInterface() );
auto aProperties = vcl::CommandInfoProvider::GetCommandProperties(u".uno:PrintDefault"_ustr,
vcl::CommandInfoProvider::GetModuleIdentifier(xFrame));
OUString val = vcl::CommandInfoProvider::GetLabelForCommand(aProperties) + " (" + aPrinterName + ")";
SfxInPlaceClient* SfxViewShell::GetUIActiveIPClient_Impl() const
{ // this method is needed as long as SFX still manages the border space for ChildWindows (see SfxFrame::Resize)
std::vector< SfxInPlaceClient* >& rClients = pImpl->GetIPClients_Impl(); if ( rClients.empty() ) return nullptr;
for (SfxInPlaceClient* pIPClient : rClients)
{ if ( pIPClient->IsUIActive() ) return pIPClient;
}
void SfxViewShell::OuterResizePixel
( const Point& /*rToolOffset*/,// Upper left corner Tools in Frame-Window const Size& /*rSize*/ // All available sizes.
)
voidAppViewSh::OuterViewResizePixel(constPoint&rOfs,constSize&rSz) { // Calculate Tool position and size externally, do not set! // (due to the following Border calculation) PointaHLinPos...;SizeaHLinSz...; ...
// Calculate and Set a Border of Tools which matches rSize. SvBorderaBorder... SetBorderPixel(aBorder);// Allow Positioning from here on.
voidAppViewSh::InnerViewResizePixel(constPoint&rOfs,constSize&rSz) { // Calculate Tool position and size internally, do not set! // (due to the following Border calculation) PointaHLinPos...;SizeaHLinSz...; ...
// Calculate and Set a Border of Tools which matches rSize. SvBorderaBorder... SetBorderPixel(aBorder);// Allow Positioning from here on.
if( pWindow )
{ // Disable automatic GUI mirroring (right-to-left) for document windows
pWindow->EnableRTL( false );
}
if ( bHadFocus && pWindow )
pWindow->GrabFocus(); //TODO/CLEANUP //Do we still need this Method?! //SfxGetpApp()->GrabFocus( pWindow );
}
ViewShellDocId SfxViewShell::mnCurrentDocId(0);
SfxViewShell::SfxViewShell
(
SfxViewFrame& rViewFrame, /* <SfxViewFrame>, which will be
displayed in this View */
SfxViewShellFlags nFlags /* See <SfxViewShell-Flags> */
)
auto it = aMap.find("SignatureCertificate"); if (rCertificateOrName.Is())
{ if (rCertificateOrName.m_xCertificate.is())
{
aMap["SignatureCertificate"] <<= rCertificateOrName.m_xCertificate;
} else
{
aMap["SignatureCertificate"] <<= rCertificateOrName.m_aName;
}
} elseif (it != aMap.end())
{
aMap.erase(it);
}
xShape->setPropertyValue("InteropGrabBag", uno::Any(aMap.getAsConstPropertyValueList())); if (!rCertificateOrName.Is())
{ // The shape's property is now reset, so the doc model is no longer modified.
GetObjectShell()->SetModified(false);
}
}
comphelper::SequenceAsHashMap aMap(xShape->getPropertyValue("InteropGrabBag")); auto it = aMap.find("SignatureCertificate"); if (it == aMap.end())
{ return {};
}
OUString SfxViewShell::GetSelectionText
( bool/*bCompleteWords*/, /* FALSE (default)
Only the actual selected text is returned.
TRUE
The selected text is expanded so that only
whole words are returned. As word separators
these are used: white spaces and punctuation ".,;"and single anddouble quotes.
*/ bool/*bOnlyASample*/ /* used by some dialogs to avoid constructing monster strings e.g. in calc */
)
// returns the first shell of spec. type viewing the specified doc.
SfxViewShell* SfxViewShell::GetFirst
( bool bOnlyVisible, const std::function< bool ( const SfxViewShell& ) >& isViewShell
)
{ // search for a SfxViewShell of the specified type
std::vector<SfxViewShell*> &rShells = SfxGetpApp()->GetViewShells_Impl(); for (SfxViewShell* pShell : rShells)
{ if ( pShell )
{ // This code used to check that the frame exists in the other list, // because of https://bz.apache.org/ooo/show_bug.cgi?id=62084, with the explanation: // sometimes dangling SfxViewShells exist that point to a dead SfxViewFrame // these ViewShells shouldn't be accessible anymore // a destroyed ViewFrame is not in the ViewFrame array anymore, so checking this array helps // That doesn't seem to be needed anymore, but keep an assert, just in case.
assert(std::find(SfxGetpApp()->GetViewFrames_Impl().begin(), SfxGetpApp()->GetViewFrames_Impl().end(),
&pShell->GetViewFrame()) != SfxGetpApp()->GetViewFrames_Impl().end()); if ( ( !bOnlyVisible || pShell->GetViewFrame().IsVisible() ) && (!isViewShell || isViewShell(*pShell))) return pShell;
}
}
return nullptr;
}
// returns the next shell of spec. type viewing the specified doc.
SfxViewShell* SfxViewShell::GetNext
( const SfxViewShell& rPrev, bool bOnlyVisible, const std::function<bool ( const SfxViewShell& )>& isViewShell
)
{
std::vector<SfxViewShell*> &rShells = SfxGetpApp()->GetViewShells_Impl();
size_t nPos; for ( nPos = 0; nPos < rShells.size(); ++nPos ) if ( rShells[nPos] == &rPrev ) break;
bool SfxViewShell::ExecKey_Impl(const KeyEvent& aKey)
{ bool setModuleConfig = false; // In case libreofficekit is active, we will re-set the module config class. if (!pImpl->m_xAccExec)
{
pImpl->m_xAccExec = ::svt::AcceleratorExecute::createAcceleratorHelper();
pImpl->m_xAccExec->init(::comphelper::getProcessComponentContext(),
rFrame.GetFrame().GetFrameInterface());
setModuleConfig = true;
}
if (comphelper::LibreOfficeKit::isActive())
{ // Get the module name. const css::uno::Reference< css::uno::XComponentContext >& xContext (::comphelper::getProcessComponentContext());
css::uno::Reference< css::frame::XModuleManager2 > xModuleManager(css::frame::ModuleManager::create(xContext));
OUString sModule = xModuleManager->identify(rFrame.GetFrame().GetFrameInterface());
// Get the language name.
OUString viewLang = GetLOKLanguageTag().getBcp47();
// Merge them & have a key.
OUString key = sModule + viewLang;
// Check it in configurations map. Create a configuration manager if there isn't one for the key.
std::unordered_map<OUString, css::uno::Reference<css::ui::XAcceleratorConfiguration>>& acceleratorConfs = SfxApplication::Get()->GetAcceleratorConfs_Impl(); if (acceleratorConfs.find(key) == acceleratorConfs.end())
{ // Create a new configuration manager for the module.
// We have set the language. Time to create the config manager.
acceleratorConfs[key] = svt::AcceleratorExecute::lok_createNewAcceleratorConfiguration(::comphelper::getProcessComponentContext(), sModule);
if (!pImpl->m_pLibreOfficeKitViewCallback) return;
// Ask other views to tell us about their cursors.
SfxViewShell* pViewShell = SfxViewShell::GetFirst(); while (pViewShell)
{ if (pViewShell->GetDocId() == GetDocId())
pViewShell->NotifyCursor(this);
pViewShell = SfxViewShell::GetNext(*pViewShell);
}
}
if (pImpl->m_pLibreOfficeKitViewCallback)
pImpl->m_pLibreOfficeKitViewCallback->dumpState(rState);
}
staticbool ignoreLibreOfficeKitViewCallback(int nType, const SfxViewShell_Impl* pImpl)
{ if (!comphelper::LibreOfficeKit::isActive()) returntrue;
if (comphelper::LibreOfficeKit::isTiledPainting())
{ switch (nType)
{ case LOK_CALLBACK_FORM_FIELD_BUTTON: case LOK_CALLBACK_TEXT_SELECTION: case LOK_CALLBACK_COMMENT: case LOK_CALLBACK_DOCUMENT_SIZE_CHANGED: break; default: // Reject e.g. invalidate during paint. returntrue;
}
}
if (pImpl->m_bTiledSearching)
{ switch (nType)
{ case LOK_CALLBACK_TEXT_SELECTION: case LOK_CALLBACK_TEXT_VIEW_SELECTION: case LOK_CALLBACK_TEXT_SELECTION_START: case LOK_CALLBACK_TEXT_SELECTION_END: case LOK_CALLBACK_GRAPHIC_SELECTION: case LOK_CALLBACK_GRAPHIC_VIEW_SELECTION: returntrue;
}
}
returnfalse;
}
void SfxViewShell::libreOfficeKitViewInvalidateTilesCallback(const tools::Rectangle* pRect, int nPart, int nMode) const
{ if (ignoreLibreOfficeKitViewCallback(LOK_CALLBACK_INVALIDATE_TILES, pImpl.get())) return; if (pImpl->m_pLibreOfficeKitViewCallback)
pImpl->m_pLibreOfficeKitViewCallback->libreOfficeKitViewInvalidateTilesCallback(pRect, nPart, nMode); else
SAL_INFO( "sfx.view", "SfxViewShell::libreOfficeKitViewInvalidateTilesCallback no callback set!");
}
void SfxViewShell::libreOfficeKitViewCallbackWithViewId(int nType, const OString& pPayload, int nViewId) const
{ if (ignoreLibreOfficeKitViewCallback(nType, pImpl.get())) return; if (pImpl->m_pLibreOfficeKitViewCallback)
pImpl->m_pLibreOfficeKitViewCallback->libreOfficeKitViewCallbackWithViewId(nType, pPayload, nViewId); else
SAL_INFO( "sfx.view", "SfxViewShell::libreOfficeKitViewCallbackWithViewId no callback set! Dropped payload of type "
<< lokCallbackTypeToString(nType) << ": [" << pPayload << ']');
}
void SfxViewShell::libreOfficeKitViewCallback(int nType, const OString& pPayload) const
{ if (ignoreLibreOfficeKitViewCallback(nType, pImpl.get())) return; if (pImpl->m_pLibreOfficeKitViewCallback)
pImpl->m_pLibreOfficeKitViewCallback->libreOfficeKitViewCallback(nType, pPayload); else
SAL_INFO( "sfx.view", "SfxViewShell::libreOfficeKitViewCallback no callback set! Dropped payload of type "
<< lokCallbackTypeToString(nType) << ": [" << pPayload << ']');
}
void SfxViewShell::libreOfficeKitViewUpdatedCallback(int nType) const
{ if (ignoreLibreOfficeKitViewCallback(nType, pImpl.get())) return; if (pImpl->m_pLibreOfficeKitViewCallback)
pImpl->m_pLibreOfficeKitViewCallback->libreOfficeKitViewUpdatedCallback(nType); else
SAL_INFO( "sfx.view", "SfxViewShell::libreOfficeKitViewUpdatedCallback no callback set! Dropped payload of type "
<< lokCallbackTypeToString(nType));
}
void SfxViewShell::libreOfficeKitViewUpdatedCallbackPerViewId(int nType, int nViewId, int nSourceViewId) const
{ if (ignoreLibreOfficeKitViewCallback(nType, pImpl.get())) return; if (pImpl->m_pLibreOfficeKitViewCallback)
pImpl->m_pLibreOfficeKitViewCallback->libreOfficeKitViewUpdatedCallbackPerViewId(nType, nViewId, nSourceViewId); else
SAL_INFO( "sfx.view", "SfxViewShell::libreOfficeKitViewUpdatedCallbackPerViewId no callback set! Dropped payload of type "
<< lokCallbackTypeToString(nType));
}
void SfxViewShell::libreOfficeKitViewAddPendingInvalidateTiles()
{ if (pImpl->m_pLibreOfficeKitViewCallback)
pImpl->m_pLibreOfficeKitViewCallback->libreOfficeKitViewAddPendingInvalidateTiles(); else
SAL_INFO( "sfx.view", "SfxViewShell::libreOfficeKitViewAddPendingInvalidateTiles no callback set!");
}
// If we want de-CH, and the de localisation is available, we don't want to use de-DE as then // the magic in Translate::get() won't turn ess-zet into double s. if (rBcp47LanguageTag == "de-CH")
maLOKLanguageTag = std::move(aTag); else
maLOKLanguageTag = std::move(aFallbackTag);
}
LOKDocumentFocusListener& SfxViewShell::GetLOKDocumentFocusListener()
{ if (mpLOKDocumentFocusListener) return *mpLOKDocumentFocusListener;
mpLOKDocumentFocusListener = new LOKDocumentFocusListener(this); return *mpLOKDocumentFocusListener;
}
void SfxViewShell::SetLOKLocale(const OUString& rBcp47LanguageTag)
{
maLOKLocale = LanguageTag(rBcp47LanguageTag, true).makeFallback(); if (this == Current())
{ // update the current LOK language and locale for the dialog tunneling
comphelper::LibreOfficeKit::setLanguageTag(GetLOKLanguageTag());
comphelper::LibreOfficeKit::setLocale(GetLOKLocale());
}
}
ViewShellDocId SfxViewShell::GetDocId() const
{
assert(pImpl->m_nDocId >= ViewShellDocId(0) && "m_nDocId should have been initialized, but it is invalid."); return pImpl->m_nDocId;
}
for (SfxInPlaceClient* pIPClient : rClients)
{ if ( pIPClient->IsObjectInPlaceActive() ) // client is active, notify client that the VisArea might have changed
pIPClient->VisAreaChanged();
}
}
// this method is called when a client is created if (pIPClient->IsObjectInPlaceActive()) return;
// object in client is currently not active // check if the object wants to be activated always or when it becomes at least partially visible // TODO/LATER: maybe we should use the scaled area instead of the ObjArea?! if (bAlwaysActive || (bActiveWhenVisible && rVisArea.Overlaps(pIPClient->GetObjArea())))
{ try
{
pIPClient->GetObject()->changeState( embed::EmbedStates::INPLACE_ACTIVE );
} catch (const uno::Exception&)
{
TOOLS_WARN_EXCEPTION("sfx.view", "SfxViewShell::CheckIPClient_Impl");
}
}
}
// there should be no old listener, but if there is one, it should be disconnected if ( pImpl->xClipboardListener.is() )
pImpl->xClipboardListener->DisconnectViewShell();
pImpl->xClipboardListener = new SfxClipboardChangeListener( this, GetClipboardNotifier() );
}
// create container from menu
aEvent.ActionTriggerContainer = ::framework::ActionTriggerHelper::CreateActionTriggerContainerFromMenu(
rIn, &rMenuIdentifier);
// get selection from controller
aEvent.Selection.set( GetController(), uno::UNO_QUERY );
// call interceptors
std::unique_lock g(pImpl->aMutex);
std::vector<uno::Reference< ui::XContextMenuInterceptor>> aInterceptors =
pImpl->aInterceptorContainer.getElements(g);
g.unlock(); for (constauto & rListener : aInterceptors )
{ try
{
ui::ContextMenuInterceptorAction eAction;
{
SolarMutexReleaser rel;
eAction = rListener->notifyContextMenuExecute( aEvent );
} switch ( eAction )
{ case ui::ContextMenuInterceptorAction_CANCELLED : // interceptor does not want execution returnfalse; case ui::ContextMenuInterceptorAction_EXECUTE_MODIFIED : // interceptor wants his modified menu to be executed
bModified = true; break; case ui::ContextMenuInterceptorAction_CONTINUE_MODIFIED : // interceptor has modified menu, but allows for calling other interceptors
bModified = true; continue; case ui::ContextMenuInterceptorAction_IGNORED : // interceptor is indifferent continue; default:
OSL_FAIL("Wrong return value of ContextMenuInterceptor!"); continue;
}
} catch (...)
{
g.lock();
pImpl->aInterceptorContainer.removeInterface(g, rListener);
g.unlock();
}
break;
}
if (bModified)
{ // container was modified, create a new menu out of it
rOut = new VCLXPopupMenu();
::framework::ActionTriggerHelper::CreateMenuFromActionTriggerContainer(rOut, aEvent.ActionTriggerContainer);
}
// create container from menu
aEvent.ActionTriggerContainer = ::framework::ActionTriggerHelper::CreateActionTriggerContainerFromMenu(
rPopupMenu, &rMenuIdentifier);
// get selection from controller
aEvent.Selection = css::uno::Reference< css::view::XSelectionSupplier >( GetController(), css::uno::UNO_QUERY );
// call interceptors
std::unique_lock g(pImpl->aMutex);
std::vector<uno::Reference< ui::XContextMenuInterceptor>> aInterceptors =
pImpl->aInterceptorContainer.getElements(g);
g.unlock(); for (constauto & rListener : aInterceptors )
{ try
{
css::ui::ContextMenuInterceptorAction eAction;
{
SolarMutexReleaser rel;
eAction = rListener->notifyContextMenuExecute( aEvent );
} switch ( eAction )
{ case css::ui::ContextMenuInterceptorAction_CANCELLED: // interceptor does not want execution returnfalse; case css::ui::ContextMenuInterceptorAction_EXECUTE_MODIFIED: // interceptor wants his modified menu to be executed
bModified = true; break; case css::ui::ContextMenuInterceptorAction_CONTINUE_MODIFIED: // interceptor has modified menu, but allows for calling other interceptors
bModified = true; continue; case css::ui::ContextMenuInterceptorAction_IGNORED: // interceptor is indifferent continue; default:
SAL_WARN( "sfx.view", "Wrong return value of ContextMenuInterceptor!" ); continue;
}
} catch (...)
{
g.lock();
pImpl->aInterceptorContainer.removeInterface(g, rListener);
g.unlock();
}
break;
}
if ( bModified )
{
rPopupMenu->clear();
::framework::ActionTriggerHelper::CreateMenuFromActionTriggerContainer(rPopupMenu, aEvent.ActionTriggerContainer);
}
¤ Diese beiden folgenden Angebotsgruppen bietet das Unternehmen0.124Angebot
(Wie Sie bei der Firma Beratungs- und Dienstleistungen beauftragen können 2026-09-28)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.