sc/source/ui/cctrl/checklistmenu.cxx |   63 +++++++++++++++++++++++++++++++++--
 sc/source/ui/inc/checklistmenu.hxx   |   22 ++++++++++++
 2 files changed, 83 insertions(+), 2 deletions(-)

New commits:
commit a525895a5f820350dc307969b1e8fd5d218a1ddd
Author:     Caolán McNamara <caolan.mcnam...@collabora.com>
AuthorDate: Mon May 13 10:43:20 2024 +0100
Commit:     Caolán McNamara <caolan.mcnam...@collabora.com>
CommitDate: Tue May 14 17:34:23 2024 +0200

    Resolves: tdf#146326 restore focus on autofilter submenu popdown
    
    to where it was before the submenu popup, unless the keyboard was used
    in the submenu, in which case restore focus to the menu instead.
    
    Change-Id: Iaa24b4eadf206b877a093529678667927488de8c
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/167580
    Tested-by: Jenkins
    Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com>

diff --git a/sc/source/ui/cctrl/checklistmenu.cxx 
b/sc/source/ui/cctrl/checklistmenu.cxx
index 60078c335437..1d720cb3b0dd 100644
--- a/sc/source/ui/cctrl/checklistmenu.cxx
+++ b/sc/source/ui/cctrl/checklistmenu.cxx
@@ -77,6 +77,10 @@ IMPL_LINK_NOARG(ScCheckListMenuControl, RowActivatedHdl, 
weld::TreeView&, bool)
 
 IMPL_LINK(ScCheckListMenuControl, MenuKeyInputHdl, const KeyEvent&, rKEvt, 
bool)
 {
+    // Assume that once the keyboard is used that focus should restore to this 
menu
+    // on dismissing a submenu
+    SetRestoreFocus(ScCheckListMenuControl::RestoreFocus::Menu);
+
     const vcl::KeyCode& rKeyCode = rKEvt.GetKeyCode();
 
     switch (rKeyCode.GetCode())
@@ -328,17 +332,65 @@ void ScCheckListMenuControl::launchSubMenu()
     if (!mxMenu->get_selected(mxScratchIter.get()))
         return;
 
+    meRestoreFocus = DetermineRestoreFocus();
+
     tools::Rectangle aRect = GetSubMenuParentRect();
     pSubMenu->StartPopupMode(mxMenu.get(), aRect);
 
     mxMenu->select(*mxScratchIter);
+
     pSubMenu->GrabFocus();
 }
 
+ScCheckListMenuControl::RestoreFocus 
ScCheckListMenuControl::DetermineRestoreFocus() const
+{
+    if (mxEdSearch->has_focus())
+        return RestoreFocus::EdSearch;
+    if (mpChecks->has_focus())
+        return RestoreFocus::Checks;
+    if (mxChkToggleAll->has_focus())
+        return RestoreFocus::ChkToggleAll;
+    if (mxChkLockChecked->has_focus())
+        return RestoreFocus::ChkLockChecked;
+    if (mxBtnSelectSingle->has_focus())
+        return RestoreFocus::BtnSelectSingle;
+    if (mxBtnUnselectSingle->has_focus())
+        return RestoreFocus::BtnUnselectSingle;
+    return RestoreFocus::Menu;
+}
+
+void ScCheckListMenuControl::RestorePreviousFocus()
+{
+    switch (meRestoreFocus)
+    {
+        case RestoreFocus::EdSearch:
+            mxEdSearch->grab_focus();
+            break;
+        case RestoreFocus::Checks:
+            mpChecks->grab_focus();
+            break;
+        case RestoreFocus::ChkToggleAll:
+            mxChkToggleAll->grab_focus();
+            break;
+        case RestoreFocus::ChkLockChecked:
+            mxChkLockChecked->grab_focus();
+            break;
+        case RestoreFocus::BtnSelectSingle:
+            mxBtnSelectSingle->grab_focus();
+            break;
+        case RestoreFocus::BtnUnselectSingle:
+            mxBtnUnselectSingle->grab_focus();
+            break;
+        default:
+            mxMenu->grab_focus();
+            break;
+    }
+}
+
 IMPL_LINK_NOARG(ScCheckListMenuControl, PostPopdownHdl, void*, void)
 {
     mnAsyncPostPopdownId = nullptr;
-    mxMenu->grab_focus();
+    RestorePreviousFocus();
 }
 
 IMPL_LINK(ScCheckListMenuControl, MouseEnterHdl, const MouseEvent&, rMEvt, 
bool)
@@ -522,6 +574,7 @@ 
ScCheckListMenuControl::ScCheckListMenuControl(weld::Widget* pParent, ScViewData
     , mrViewData(rViewData)
     , mnAsyncPostPopdownId(nullptr)
     , mnAsyncSetDropdownPosId(nullptr)
+    , meRestoreFocus(RestoreFocus::Menu)
     , mbHasDates(bHasDates)
     , mbIsPoppedUp(false)
     , maOpenTimer(this)
@@ -1815,8 +1868,14 @@ IMPL_LINK(ScListSubMenuControl, MenuKeyInputHdl, const 
KeyEvent&, rKEvt, bool)
 {
     bool bConsumed = false;
     const vcl::KeyCode& rKeyCode = rKEvt.GetKeyCode();
+    const sal_uInt16 eKeyCode = rKeyCode.GetCode();
 
-    switch (rKeyCode.GetCode())
+    // Assume that once the keyboard is used that focus should restore to the
+    // parent menu
+    if (eKeyCode != KEY_ESCAPE)
+        
mrParentControl.SetRestoreFocus(ScCheckListMenuControl::RestoreFocus::Menu);
+
+    switch (eKeyCode)
     {
         case KEY_ESCAPE:
         case KEY_LEFT:
diff --git a/sc/source/ui/inc/checklistmenu.hxx 
b/sc/source/ui/inc/checklistmenu.hxx
index 8e24baef433b..558ef9f47e37 100644
--- a/sc/source/ui/inc/checklistmenu.hxx
+++ b/sc/source/ui/inc/checklistmenu.hxx
@@ -96,6 +96,18 @@ public:
     };
     typedef std::set<ResultEntry> ResultType;
 
+
+    enum RestoreFocus
+    {
+        Menu,
+        EdSearch,
+        Checks,
+        ChkToggleAll,
+        ChkLockChecked,
+        BtnSelectSingle,
+        BtnUnselectSingle
+    };
+
     struct MenuItemData
     {
         bool     mbEnabled:1;
@@ -190,6 +202,11 @@ public:
 
     void addFields(const std::vector<OUString>& aFields);
     tools::Long getField();
+
+    void SetRestoreFocus(RestoreFocus eFocus)
+    {
+        meRestoreFocus = eFocus;
+    }
 private:
 
     std::vector<MenuItemData>         maMenuItems;
@@ -266,6 +283,9 @@ private:
 
     void DropPendingEvents();
 
+    RestoreFocus DetermineRestoreFocus() const;
+    void RestorePreviousFocus();
+
 private:
     std::unique_ptr<weld::Builder> mxBuilder;
     std::unique_ptr<weld::Popover> mxPopover;
@@ -316,6 +336,8 @@ private:
     ImplSVEvent* mnAsyncPostPopdownId;
     ImplSVEvent* mnAsyncSetDropdownPosId;
 
+    RestoreFocus meRestoreFocus;
+
     bool mbHasDates;
     bool mbIsPoppedUp;
 

Reply via email to