include/sfx2/sfxsids.hrc | 2 include/svl/srchitem.hxx | 3 include/svx/srchdlg.hxx | 3 officecfg/registry/data/org/openoffice/Office/Accelerators.xcu | 4 - sc/sdi/tabvwsh.sdi | 1 sc/source/ui/inc/tabvwsh.hxx | 2 sc/source/ui/view/tabvwsh4.cxx | 37 ++++++++++ sd/sdi/_drvwsh.sdi | 5 + sd/source/ui/inc/DrawViewShell.hxx | 2 sd/source/ui/view/drviewse.cxx | 36 +++++++++ sfx2/sdi/sfx.sdi | 1 svl/source/items/srchitem.cxx | 6 + svx/source/dialog/srchdlg.cxx | 26 +++++-- sw/inc/view.hxx | 1 sw/sdi/_viewsh.sdi | 5 + sw/source/uibase/uiview/viewsrch.cxx | 27 +++++++ 16 files changed, 149 insertions(+), 12 deletions(-)
New commits: commit 0e540f04389a0565f57159880c46de60197e77ad Author: Parth Raiyani <parth.raiy...@collabora.com> AuthorDate: Tue Sep 23 14:58:58 2025 +0530 Commit: Szymon Kłos <szymon.k...@collabora.com> CommitDate: Thu Sep 25 09:27:24 2025 +0200 find-replace: set initial focus on Replace tab when shortcut is used - Added a new feature to set the initial focus on the 'Replace' tab in the search dialog. - Introduced a boolean property 'InitialFocusReplace' to manage this behavior and updates related constructors, methods, and UI bindings accordingly. - Fixed accessibility issue by setting initial focus on replace tab when replace shortcut is triggered in writer, calc, impress, draw Change-Id: Ib4833d817ee58ec13d377123de6c963f2817b626 Signed-off-by: Parth Raiyani <parth.raiy...@collabora.com> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/191289 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com> Reviewed-by: Szymon Kłos <szymon.k...@collabora.com> diff --git a/include/sfx2/sfxsids.hrc b/include/sfx2/sfxsids.hrc index 10400ccf6365..003b4f0d0fa8 100644 --- a/include/sfx2/sfxsids.hrc +++ b/include/sfx2/sfxsids.hrc @@ -510,7 +510,7 @@ class SvxZoomItem; #define SID_BASICSTOP (SID_SFX_START + 958) #define SID_BASICCHOOSER (SID_SFX_START + 959) #define SID_GALLERY (SID_SFX_START + 960) -#define SID_SEARCH_DLG (SID_SFX_START + 961) +#define SID_SEARCH_DLG TypedWhichId<SfxBoolItem>(SID_SFX_START + 961) #define SID_SEARCH_QUIET (SID_SFX_START + 1684) #define SID_SEARCH (SID_SFX_START + 1685) #define SID_EXPORT_DIALOG (SID_SFX_START + 965) diff --git a/include/svl/srchitem.hxx b/include/svl/srchitem.hxx index f9c71d4e767b..911c5b2fcb71 100644 --- a/include/svl/srchitem.hxx +++ b/include/svl/srchitem.hxx @@ -86,6 +86,7 @@ class SVL_DLLPUBLIC SvxSearchItem final : // Start search at this point (absolute twips). sal_Int32 m_nStartPointX; sal_Int32 m_nStartPointY; + bool m_bInitialFocusOnReplace; virtual void ImplCommit() override; @@ -169,6 +170,8 @@ public: SvxSearchApp GetAppFlag() const { return m_nAppFlag; } void SetAppFlag(SvxSearchApp nNewAppFlag) { m_nAppFlag = nNewAppFlag; } + bool GetInitialFocusOnReplace() const { return m_bInitialFocusOnReplace; } + void SetInitialFocusOnReplace(bool bVal) { m_bInitialFocusOnReplace = bVal; } inline bool IsLevenshtein() const; void SetLevenshtein( bool bVal ); diff --git a/include/svx/srchdlg.hxx b/include/svx/srchdlg.hxx index f403f033283e..2f9cdd792848 100644 --- a/include/svx/srchdlg.hxx +++ b/include/svx/srchdlg.hxx @@ -123,7 +123,7 @@ friend class SvxSearchDialogWrapper; friend class SvxJSearchOptionsDialog; public: - SvxSearchDialog(weld::Window* pParent, SfxChildWindow* pChildWin, SfxBindings& rBind ); + SvxSearchDialog(weld::Window* pParent, SfxChildWindow* pChildWin, SfxBindings& rBind, bool bInitialFocusOnReplace = false ); virtual ~SvxSearchDialog() override; virtual void ChildWinDispose() override; @@ -152,6 +152,7 @@ private: bool bWriter; bool bSearch; bool bFormat; + bool m_bInitialFocusOnReplace; bool bReplaceBackwards; SearchOptionFlags nOptions; bool bSet; diff --git a/officecfg/registry/data/org/openoffice/Office/Accelerators.xcu b/officecfg/registry/data/org/openoffice/Office/Accelerators.xcu index a411e687f773..96163849a4e9 100644 --- a/officecfg/registry/data/org/openoffice/Office/Accelerators.xcu +++ b/officecfg/registry/data/org/openoffice/Office/Accelerators.xcu @@ -143,7 +143,7 @@ Ctrl+Shift+u aka U_SHIFT_MOD1 under GTK/IBUS is for unicode key input <node oor:name="H_MOD1" oor:op="replace"> <prop oor:name="Command"> <value xml:lang="x-no-translate">L10N SHORTCUTS - NO TRANSLATE</value> - <value xml:lang="en-US" install:module="unxwnt">.uno:SearchDialog</value> + <value xml:lang="en-US" install:module="unxwnt">.uno:SearchDialog?InitialFocusReplace:bool=true</value> </prop> </node> <node oor:name="G_MOD1" oor:op="replace"> @@ -463,7 +463,7 @@ Ctrl+Shift+u aka U_SHIFT_MOD1 under GTK/IBUS is for unicode key input <node oor:name="H_MOD1" oor:op="replace"> <prop oor:name="Command"> <value xml:lang="x-no-translate">L10N SHORTCUTS - NO TRANSLATE</value> - <value xml:lang="en-US" install:module="unxwnt">.uno:SearchDialog</value> + <value xml:lang="en-US" install:module="unxwnt">.uno:SearchDialog?InitialFocusReplace:bool=true</value> </prop> </node> <node oor:name="N_MOD1" oor:op="replace"> diff --git a/sc/sdi/tabvwsh.sdi b/sc/sdi/tabvwsh.sdi index 109c2faa8aa8..6506fe8e858b 100644 --- a/sc/sdi/tabvwsh.sdi +++ b/sc/sdi/tabvwsh.sdi @@ -192,6 +192,7 @@ interface TableEditView // search/replace + SID_SEARCH_DLG [ ExecMethod = SearchDialogHdl; StateMethod = GetState; ] FID_SEARCH_NOW [ ExecMethod = ExecSearch; StateMethod = NoState; ] SID_SEARCH_ITEM [ ExecMethod = ExecSearch; StateMethod = GetState; ] SID_SEARCH_OPTIONS [ ExecMethod = NoExec; StateMethod = GetState; ] diff --git a/sc/source/ui/inc/tabvwsh.hxx b/sc/source/ui/inc/tabvwsh.hxx index ea40ff8fef20..359c0fefdf9e 100644 --- a/sc/source/ui/inc/tabvwsh.hxx +++ b/sc/source/ui/inc/tabvwsh.hxx @@ -483,6 +483,8 @@ public: void SetInsertWizardUndoMark(); + DECL_LINK(SearchDialogHdl, SfxRequest&, void); + private: void ExecuteMoveTable( SfxRequest& rReq ); void DoMoveTableFromDialog( SfxRequest& rReq, const VclPtr<AbstractScMoveTableDlg>& pDlg ); diff --git a/sc/source/ui/view/tabvwsh4.cxx b/sc/source/ui/view/tabvwsh4.cxx index 7a0195c176f5..84d91fd11807 100644 --- a/sc/source/ui/view/tabvwsh4.cxx +++ b/sc/source/ui/view/tabvwsh4.cxx @@ -89,6 +89,9 @@ #include <LibreOfficeKit/LibreOfficeKitEnums.h> #include <comphelper/lok.hxx> #include <sfx2/sidebar/SidebarController.hxx> +#include <sfx2/dispatch.hxx> +#include <svl/srchitem.hxx> +#include <svx/srchdlg.hxx> using namespace com::sun::star; using namespace sfx2::sidebar; @@ -344,6 +347,40 @@ void ScTabViewShell::UpdateOleZoom() } } +IMPL_LINK(ScTabViewShell, SearchDialogHdl, SfxRequest&, rReq, void) +{ + // Get the parameter from the request + const SfxItemSet* pArgs = rReq.GetArgs(); + bool bInitialFocusOnReplace = false; + + if (pArgs) + { + const SfxBoolItem* pBoolItem = pArgs->GetItemIfSet(SID_SEARCH_DLG, false); + if (pBoolItem) + bInitialFocusOnReplace = pBoolItem->GetValue(); + } + + // Get existing search item to preserve settings + std::unique_ptr<SvxSearchItem> pSearchItem; + std::unique_ptr<SvxSearchItem> pExistingItem; + if (GetViewData().GetBindings().QueryState(SID_SEARCH_ITEM, pExistingItem) >= SfxItemState::DEFAULT && pExistingItem) + { + pSearchItem.reset(pExistingItem->Clone()); + } + else + { + pSearchItem = std::make_unique<SvxSearchItem>(SID_SEARCH_ITEM); + } + + // Only set the focus parameter, preserving all other settings + pSearchItem->SetInitialFocusOnReplace(bInitialFocusOnReplace); + + // Execute the search dialog with the configured item + const SfxPoolItem* ppArgs[] = { pSearchItem.get(), nullptr }; + GetViewData().GetDispatcher().Execute(SID_SEARCH_ITEM, SfxCallMode::SYNCHRON, ppArgs); + GetViewFrame().ToggleChildWindow(SvxSearchDialogWrapper::GetChildWindowId()); +} + void ScTabViewShell::InnerResizePixel( const Point &rOfs, const Size &rSize, bool inplaceEditModeChange ) { Size aNewSize( rSize ); diff --git a/sd/sdi/_drvwsh.sdi b/sd/sdi/_drvwsh.sdi index 7af2d314744c..9301c094a545 100644 --- a/sd/sdi/_drvwsh.sdi +++ b/sd/sdi/_drvwsh.sdi @@ -2463,6 +2463,11 @@ interface DrawView ExecMethod = Execute ; StateMethod = GetMenuState ; ] + SID_SEARCH_DLG + [ + ExecMethod = SearchDialogHdl ; + StateMethod = GetMenuState ; + ] SID_EXTRUSION_TOGGLE [ ExecMethod = FuTemporary ; diff --git a/sd/source/ui/inc/DrawViewShell.hxx b/sd/source/ui/inc/DrawViewShell.hxx index e7022a61ca42..5931def882d4 100644 --- a/sd/source/ui/inc/DrawViewShell.hxx +++ b/sd/source/ui/inc/DrawViewShell.hxx @@ -391,6 +391,8 @@ public: const css::uno::Reference<css::presentation::XSlideShow> & getXSlideShowInstance(); void destroyXSlideShowInstance(); + DECL_LINK(SearchDialogHdl, SfxRequest&, void); + protected: DECL_DLLPRIVATE_LINK( ClipboardChanged, TransferableDataHelper*, void ); DECL_DLLPRIVATE_LINK( TabSplitHdl, TabBar *, void ); diff --git a/sd/source/ui/view/drviewse.cxx b/sd/source/ui/view/drviewse.cxx index eaad51be823c..cbf644013247 100644 --- a/sd/source/ui/view/drviewse.cxx +++ b/sd/source/ui/view/drviewse.cxx @@ -104,6 +104,8 @@ #include <SlideSorterViewShell.hxx> #include <controller/SlideSorterController.hxx> #include <controller/SlsClipboard.hxx> +#include <svl/srchitem.hxx> +#include <svx/srchdlg.hxx> using namespace ::com::sun::star; using namespace ::com::sun::star::uno; @@ -799,6 +801,40 @@ void DrawViewShell::FuDeleteSelectedObjects() mpDrawView->DeleteMarked(); } +IMPL_LINK(DrawViewShell, SearchDialogHdl, SfxRequest&, rReq, void) +{ + // Get the parameter from the request + const SfxItemSet* pArgs = rReq.GetArgs(); + bool bInitialFocusOnReplace = false; + + if (pArgs) + { + const SfxBoolItem* pBoolItem = pArgs->GetItemIfSet(SID_SEARCH_DLG, false); + if (pBoolItem) + bInitialFocusOnReplace = pBoolItem->GetValue(); + } + + // Get existing search item to preserve settings + std::unique_ptr<SvxSearchItem> pSearchItem; + std::unique_ptr<SvxSearchItem> pExistingItem; + if (GetViewFrame()->GetBindings().QueryState(SID_SEARCH_ITEM, pExistingItem) >= SfxItemState::DEFAULT && pExistingItem) + { + pSearchItem.reset(pExistingItem->Clone()); + } + else + { + pSearchItem = std::make_unique<SvxSearchItem>(SID_SEARCH_ITEM); + } + + // Only set the focus parameter, preserving all other settings + pSearchItem->SetInitialFocusOnReplace(bInitialFocusOnReplace); + + // Execute the search dialog with the configured item + const SfxPoolItem* ppArgs[] = { pSearchItem.get(), nullptr }; + GetViewFrame()->GetBindings().GetDispatcher()->Execute(SID_SEARCH_ITEM, SfxCallMode::SYNCHRON, ppArgs); + GetViewFrame()->ToggleChildWindow(SvxSearchDialogWrapper::GetChildWindowId()); +} + void DrawViewShell::FuSupport(SfxRequest& rReq) { if( rReq.GetSlot() == SID_STYLE_FAMILY && rReq.GetArgs()) diff --git a/sfx2/sdi/sfx.sdi b/sfx2/sdi/sfx.sdi index 72447ad71b62..386384759574 100644 --- a/sfx2/sdi/sfx.sdi +++ b/sfx2/sdi/sfx.sdi @@ -4015,6 +4015,7 @@ SfxBoolItem FocusToFindbar SID_SEARCH SfxBoolItem SearchDialog SID_SEARCH_DLG +(SfxBoolItem InitialFocusReplace SID_SEARCH_DLG) [ AutoUpdate = TRUE, FastCall = FALSE, diff --git a/svl/source/items/srchitem.cxx b/svl/source/items/srchitem.cxx index 5f37d07b7674..fdbae924fc58 100644 --- a/svl/source/items/srchitem.cxx +++ b/svl/source/items/srchitem.cxx @@ -115,7 +115,8 @@ SvxSearchItem::SvxSearchItem( const sal_uInt16 nId ) : m_bContent ( false ), m_bAsianOptions ( false ), m_nStartPointX(0), - m_nStartPointY(0) + m_nStartPointY(0), + m_bInitialFocusOnReplace(false) { EnableNotification( lcl_GetNotifyNames() ); @@ -210,7 +211,8 @@ SvxSearchItem::SvxSearchItem( const SvxSearchItem& rItem ) : m_bContent ( rItem.m_bContent ), m_bAsianOptions ( rItem.m_bAsianOptions ), m_nStartPointX(rItem.m_nStartPointX), - m_nStartPointY(rItem.m_nStartPointY) + m_nStartPointY(rItem.m_nStartPointY), + m_bInitialFocusOnReplace(rItem.m_bInitialFocusOnReplace) { EnableNotification( lcl_GetNotifyNames() ); } diff --git a/svx/source/dialog/srchdlg.cxx b/svx/source/dialog/srchdlg.cxx index 9cc7fda366e1..a08dbd88e012 100644 --- a/svx/source/dialog/srchdlg.cxx +++ b/svx/source/dialog/srchdlg.cxx @@ -239,7 +239,7 @@ void SearchAttrItemList::Remove(size_t nPos) SrchAttrInfoList::erase( begin() + nPos, begin() + nPos + nLen ); } -SvxSearchDialog::SvxSearchDialog(weld::Window* pParent, SfxChildWindow* pChildWin, SfxBindings& rBind) +SvxSearchDialog::SvxSearchDialog(weld::Window* pParent, SfxChildWindow* pChildWin, SfxBindings& rBind, bool bInitialFocusOnReplace) : SfxModelessDialogController(&rBind, pChildWin, pParent, IsMobile() ? u"svx/ui/findreplacedialog-mobile.ui"_ustr : u"svx/ui/findreplacedialog.ui"_ustr, u"FindReplaceDialog"_ustr) @@ -248,6 +248,7 @@ SvxSearchDialog::SvxSearchDialog(weld::Window* pParent, SfxChildWindow* pChildWi , bWriter(false) , bSearch(true) , bFormat(false) + , m_bInitialFocusOnReplace(bInitialFocusOnReplace) , bReplaceBackwards(false) , nOptions(SearchOptionFlags::ALL) , bSet(false) @@ -311,6 +312,7 @@ SvxSearchDialog::SvxSearchDialog(weld::Window* pParent, SfxChildWindow* pChildWi { m_xCloseBtn->hide(); m_xHelpBtn->hide(); + bSearch = !m_bInitialFocusOnReplace; m_xSearchLB->set_entry_text(u""_ustr); m_xReplaceLB->set_entry_text(u""_ustr); m_xSearchLB->grab_focus(); @@ -348,7 +350,7 @@ SvxSearchDialog::SvxSearchDialog(weld::Window* pParent, SfxChildWindow* pChildWi m_xReplaceTmplLB->set_size_request(nTermWidth, -1); Construct_Impl(); - SetReplaceCtrlsVisible(false); + SetReplaceCtrlsVisible(m_bInitialFocusOnReplace); } IMPL_LINK_NOARG(SvxSearchDialog, PresentTimeoutHdl_Impl, Timer*, void) @@ -973,9 +975,11 @@ void SvxSearchDialog::Init_Impl( bool bSearchPattern ) } m_xSearchTmplLB->show(); - if ( bConstruct ) + if ( bConstruct ) { // Grab focus only after creating + bSearch = !m_bInitialFocusOnReplace; m_xSearchTmplLB->grab_focus(); + } m_xReplaceTmplLB->show(); m_xSearchLB->hide(); m_xReplaceLB->hide(); @@ -1017,9 +1021,11 @@ void SvxSearchDialog::Init_Impl( bool bSearchPattern ) m_xSearchLB->show(); - if ( bConstruct ) + if ( bConstruct ) { // Grab focus only after creating + bSearch = !m_bInitialFocusOnReplace; m_xSearchLB->grab_focus(); + } m_xReplaceLB->show(); m_xSearchTmplLB->hide(); m_xReplaceTmplLB->hide(); @@ -1036,7 +1042,7 @@ void SvxSearchDialog::Init_Impl( bool bSearchPattern ) bDisableSearch = m_xSearchLB->get_active_text().isEmpty() && m_xSearchAttrText->get_label().isEmpty(); } - FocusHdl_Impl(*m_xSearchLB); + FocusHdl_Impl(bSearch ? *m_xSearchLB : *m_xReplaceLB); if ( bDisableSearch ) { @@ -2366,8 +2372,16 @@ SvxSearchDialogWrapper::SvxSearchDialogWrapper( vcl::Window* _pParent, sal_uInt1 SfxBindings* pBindings, SfxChildWinInfo const * pInfo ) : SfxChildWindow( _pParent, nId ) - , dialog(std::make_shared<SvxSearchDialog>(_pParent->GetFrameWeld(), this, *pBindings)) { + bool bInitialFocusOnReplace = false; + std::unique_ptr<SvxSearchItem> pItem; + if (pBindings->QueryState(SID_SEARCH_ITEM, pItem) >= SfxItemState::DEFAULT && pItem) + { + bInitialFocusOnReplace = pItem->GetInitialFocusOnReplace(); + } + + dialog = std::make_shared<SvxSearchDialog>(_pParent->GetFrameWeld(), this, *pBindings, bInitialFocusOnReplace); + SetController(dialog); dialog->Initialize( pInfo ); diff --git a/sw/inc/view.hxx b/sw/inc/view.hxx index 2d8c7814f3bd..124fe66e29ee 100644 --- a/sw/inc/view.hxx +++ b/sw/inc/view.hxx @@ -364,6 +364,7 @@ public: // #i123922# Needs to be called from a 2nd place now as a helper method sal_Int32 m_nNaviExpandedStatus = -1; void SetFormShell( FmFormShell* pSh ) { m_pFormShell = pSh; } virtual void SelectShell(); + DECL_LINK(SearchDialogHdl, SfxRequest&, void); protected: diff --git a/sw/sdi/_viewsh.sdi b/sw/sdi/_viewsh.sdi index 5f94cb17c9c3..c13b367bba90 100644 --- a/sw/sdi/_viewsh.sdi +++ b/sw/sdi/_viewsh.sdi @@ -692,6 +692,11 @@ interface BaseTextEditView /* search and replace */ + SID_SEARCH_DLG + [ + ExecMethod = SearchDialogHdl ; + StateMethod = StateSearch ; + ] SID_SEARCH_ITEM // status() [ ExecMethod = ExecSearch ; diff --git a/sw/source/uibase/uiview/viewsrch.cxx b/sw/source/uibase/uiview/viewsrch.cxx index 9d3eaa3603b5..33fae1666d59 100644 --- a/sw/source/uibase/uiview/viewsrch.cxx +++ b/sw/source/uibase/uiview/viewsrch.cxx @@ -53,6 +53,7 @@ #include <SwRewriter.hxx> #include <PostItMgr.hxx> +#include <sfx2/dispatch.hxx> using namespace com::sun::star; using namespace ::com::sun::star::lang; @@ -476,6 +477,32 @@ void SwView::ExecSearch(SfxRequest& rReq) } } +IMPL_LINK(SwView, SearchDialogHdl, SfxRequest&, rReq, void) +{ + // Get the parameter from the request + const SfxItemSet* pArgs = rReq.GetArgs(); + bool bInitialFocusOnReplace = false; + + if (pArgs) + { + const SfxBoolItem* pBoolItem = pArgs->GetItemIfSet(SID_SEARCH_DLG, false); + if (pBoolItem) + bInitialFocusOnReplace = pBoolItem->GetValue(); + } + + if (!s_pSrchItem) + s_pSrchItem = new SvxSearchItem(SID_SEARCH_ITEM); + + s_pSrchItem->SetInitialFocusOnReplace(bInitialFocusOnReplace); + + // Execute the search item to pass it to the dialog + const SfxPoolItem* ppArgs[] = { s_pSrchItem, nullptr }; + GetDispatcher().Execute(SID_SEARCH_ITEM, SfxCallMode::SYNCHRON, ppArgs); + + // Open the dialog + GetViewFrame().ToggleChildWindow(SvxSearchDialogWrapper::GetChildWindowId()); +} + bool SwView::SearchAndWrap(bool bApi) { SwSearchOptions aOpts( m_pWrtShell.get(), s_pSrchItem->GetBackward() );