office-gobmx/vcl/inc/managedmenubutton.hxx
Michael Weghorn f075fa01cb tdf#141101 tdf#101886 a11y: Restore previous focus on col/line popup close
Don't request focus for the color window
before the menu button popup opens.

Doing so would prevent properly restoring focus to the
menu button itself after the popup closes again.

Without this change in place, the call to
`MenuButton::Activate` in `MenuButton::ExecuteMenu (s. frame 14/15
in below backtrace) would already set focus to the "Automatic" button
in the color window:

        1  PushButton::GetFocus   button.cxx 1490 0x7f4acfdc83b6
        2  vcl::Window::CompatGetFocus    window.cxx 3888 0x7f4acfd9d26d
        3  vcl::Window::ImplGrabFocus mouse.cxx  384  0x7f4acfcd5215
        4  vcl::Window::GrabFocus window.cxx 2979 0x7f4acfd988e9
        5  SalInstanceWidget::grab_focus  salvtables.cxx 390  0x7f4ad046f505
        6  ColorWindow::GrabFocus tbcontrl.cxx   2127 0x7f4ad3f21af1
        7  ColorListBox::ToggleHdl    tbcontrl.cxx   4291 0x7f4ad3f313d6
        8  ColorListBox::LinkStubToggleHdl    tbcontrl.cxx   4285 0x7f4ad3f31369
        9  Link<weld::Toggleable&, void>::Call    link.hxx   111  0x7f4ad04aec71
        10 weld::Toggleable::signal_toggled   weld.hxx   1539 0x7f4ad04a77a3
        11 SalInstanceMenuButton::ActivateHdl salvtables.cxx 3075 0x7f4ad0483086
        12 SalInstanceMenuButton::LinkStubActivateHdl salvtables.cxx 3071 0x7f4ad0483043
        13 Link<MenuButton *, void>::Call link.hxx   111  0x7f4acfe9e9c1
        14 MenuButton::Activate   menubtn.cxx    237  0x7f4acfe9e136
        15 MenuButton::ExecuteMenu    menubtn.cxx    61   0x7f4acfe9cca1
        16 MenuButton::KeyInput   menubtn.cxx    226  0x7f4acfe9e092
        17 ImplHandleKey  winproc.cxx    1211 0x7f4acfdb0962
        18 ImplWindowFrameProc    winproc.cxx    2724 0x7f4acfdb6fcf
        19 SalFrame::CallCallback salframe.hxx   310  0x7f4ac5aa3dfa
        20 QtFrame::CallCallback  QtFrame.hxx    229  0x7f4ac5aa5336
        ... <More>

As a consequence, this "Automatic" button inside of the color window
would be the UI element remembered as the the one to which focus
focus should be restored when closing the popup, see the

    mxPrevFocusWin = Window::SaveFocus();

in `FloatingWindow::StartPopupMode`, which gets called like this:

    1   FloatingWindow::StartPopupMode           floatwin.cxx         824  0x7f4acfc61a61
    2   ImplDockingWindowWrapper::StartPopupMode dockmgr.cxx          846  0x7f4acfc43bd3
    3   DockingManager::StartPopupMode           dockmgr.cxx          341  0x7f4acfc412c3
    4   MenuButton::ExecuteMenu                  menubtn.cxx          94   0x7f4acfe9cfa9
    5   MenuButton::KeyInput                     menubtn.cxx          226  0x7f4acfe9e092
    6   ImplHandleKey                            winproc.cxx          1211 0x7f4acfdb0962
    7   ImplWindowFrameProc                      winproc.cxx          2724 0x7f4acfdb6fcf
    8   SalFrame::CallCallback                   salframe.hxx         310  0x7f4ac5aa3dfa
    9   QtFrame::CallCallback                    QtFrame.hxx          229  0x7f4ac5aa5336
    10  QtWidget::handleKeyEvent                 QtWidget.cxx         671  0x7f4ac5af9f38
    11  QtWidget::handleEvent                    QtWidget.cxx         707  0x7f4ac5afa094
    12  QtWidget::event                          QtWidget.cxx         730  0x7f4ac5afa1f7
    13  QApplicationPrivate::notify_helper       qapplication.cpp     3287 0x7f4ac37a2414
    14  QApplication::notify                     qapplication.cpp     2715 0x7f4ac379fd5b
    15  QCoreApplication::notifyInternal2        qcoreapplication.cpp 1123 0x7f4ac51a3c34
    16  QCoreApplication::forwardEvent           qcoreapplication.cpp 1138 0x7f4ac51a3cac
    17  QWidgetWindow::handleKeyEvent            qwidgetwindow.cpp    669  0x7f4ac38567b1
    18  QWidgetWindow::event                     qwidgetwindow.cpp    234  0x7f4ac3854924
    19  QApplicationPrivate::notify_helper       qapplication.cpp     3287 0x7f4ac37a2414
    20  QApplication::notify                     qapplication.cpp     3238 0x7f4ac37a2224
    ... <More>

and then properly restoring focus fails in
`FloatingWindow::EndPopupMode`.

Move the call to `Activate` to after showing the
popup instead. This makes sure that the actual
widget that had focus *before* the popup opened
is remembered and focus is correctly restored
on close.

The handler for the toggled signal had been added in

    commit e55a1dc163
    Date:   Wed Nov 27 14:58:00 2019 +0000

        don't put focus into unmapped windows

        defer until the color selectors are activated to grab focus, otherwise
        esc doesn't work to close a dialog under gtk3 until focus is put
        into some visible widget

which apparently already moved the focus request to later than it was
before.

With this change in place, the NVDA screen reader announces the
menu button again once the color popup closes (tdf#141101) and it also
makes opening the popup menu again right away work
by pressing Alt+Down button again on Windows or with the
gen or qt6 VCL plugins on Linux, which didn't work beforehand,
but required either using the mouse or tabbing to another UI
element and back before that keyboard shortcut would work again.

The same is true for the border line style popup (tdf#101886).

Setting the focus only when the popup shows also
makes the focus correctly be on the previously
selected color for the non-gtk3 case when opening
the popup again. (Previously, the "Automatic" button
would always have focus.)

Ensure that the required preparations for showing the
popup in the `ManagedMenuButton` subclass are still
done before executing the menu by doing what's
needed in the newly named `ManagedMenuButton::PrepareExecute`
method rather than in `Activate` and call that
one before showing the menu.

Change-Id: I82fbfea2ae8b9064979796da279750350deb742d
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/155891
Tested-by: Jenkins
Reviewed-by: Michael Weghorn <m.weghorn@posteo.de>
2023-08-22 12:48:41 +02:00

31 lines
973 B
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#pragma once
#include <vcl/toolkit/menubtn.hxx>
#include <com/sun/star/awt/XPopupMenu.hpp>
#include <com/sun/star/frame/XPopupMenuController.hpp>
class ManagedMenuButton final : public MenuButton
{
public:
ManagedMenuButton(vcl::Window* pParent, WinBits nStyle);
~ManagedMenuButton() override;
void dispose() override;
private:
void PrepareExecute() override;
css::uno::Reference<css::awt::XPopupMenu> m_xPopupMenu;
css::uno::Reference<css::frame::XPopupMenuController> m_xPopupController;
};
/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */