toolkit/inc/controls/table/defaultinputhandler.hxx    |    1 
 toolkit/inc/controls/table/tablecontrolinterface.hxx  |   12 ----
 toolkit/source/controls/svtxgridcontrol.cxx           |    4 -
 toolkit/source/controls/table/defaultinputhandler.cxx |   45 ------------------
 toolkit/source/controls/table/tablecontrol.cxx        |   43 ++++++++++++++++-
 toolkit/source/controls/table/tablecontrol_impl.hxx   |   14 +++++
 6 files changed, 57 insertions(+), 62 deletions(-)

New commits:
commit 6fc13fb03bc96eda65b91fd65ada26a162437404
Author:     Michael Weghorn <m.wegh...@posteo.de>
AuthorDate: Thu Jan 23 15:01:15 2025 +0100
Commit:     Michael Weghorn <m.wegh...@posteo.de>
CommitDate: Fri Jan 24 07:37:51 2025 +0100

    toolkit: Move TableControl key input logic into that class
    
    Move logic from DefaultInputHandler::KeyInput
    into the only caller, TableControl::KeyInput.
    
    Drop ITableControl::dispatchAction from that interface
    as TableControl is now the only caller and that one
    knows that it's TableControl::m_pImpl is a
    TableControl_Impl.
    
    Change-Id: I0445ce10f8abee17ab6e4895aba5adf42974721b
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/180662
    Tested-by: Jenkins
    Reviewed-by: Michael Weghorn <m.wegh...@posteo.de>

diff --git a/toolkit/inc/controls/table/defaultinputhandler.hxx 
b/toolkit/inc/controls/table/defaultinputhandler.hxx
index 51610b4b5d2d..40acc4a7a809 100644
--- a/toolkit/inc/controls/table/defaultinputhandler.hxx
+++ b/toolkit/inc/controls/table/defaultinputhandler.hxx
@@ -44,7 +44,6 @@ namespace svt::table
         bool MouseMove(ITableControl& _rControl, const MouseEvent& rMEvt);
         bool MouseButtonDown(ITableControl& _rControl, const MouseEvent& 
rMEvt);
         bool MouseButtonUp(ITableControl& _rControl, const MouseEvent& rMEvt);
-        static bool KeyInput(ITableControl& _rControl, const KeyEvent& rKEvt);
 
     private:
         bool delegateMouseEvent( ITableControl& i_control, const MouseEvent& 
i_event,
diff --git a/toolkit/inc/controls/table/tablecontrolinterface.hxx 
b/toolkit/inc/controls/table/tablecontrolinterface.hxx
index ee9a52785471..e5ff0cd88303 100644
--- a/toolkit/inc/controls/table/tablecontrolinterface.hxx
+++ b/toolkit/inc/controls/table/tablecontrolinterface.hxx
@@ -163,18 +163,6 @@ namespace svt::table
         */
         virtual void    showCursor() = 0;
 
-        /** dispatches an action to the table control
-
-            @return
-                <TRUE/> if the action could be dispatched successfully, 
<FALSE/> otherwise. Usual
-                failure conditions include some other instance vetoing the 
action, or impossibility
-                to execute the action at all (for instance moving up one row 
when already positioned
-                on the very first row).
-
-            @see TableControlAction
-        */
-        virtual bool    dispatchAction( TableControlAction _eAction ) = 0;
-
         /** returns selection engine*/
         virtual SelectionEngine* getSelEngine() = 0;
 
diff --git a/toolkit/source/controls/table/defaultinputhandler.cxx 
b/toolkit/source/controls/table/defaultinputhandler.cxx
index ef6e250547f8..ba00f0bb9384 100644
--- a/toolkit/source/controls/table/defaultinputhandler.cxx
+++ b/toolkit/source/controls/table/defaultinputhandler.cxx
@@ -114,51 +114,6 @@ namespace svt::table
         return delegateMouseEvent( i_tableControl, i_event, 
&MouseFunction::handleMouseUp );
     }
 
-
-    bool DefaultInputHandler::KeyInput( ITableControl& _rControl, const 
KeyEvent& rKEvt )
-    {
-        bool bHandled = false;
-
-        const vcl::KeyCode& rKeyCode = rKEvt.GetKeyCode();
-        sal_uInt16 nKeyCode = rKeyCode.GetCode();
-
-        struct ActionMapEntry
-        {
-            sal_uInt16              nKeyCode;
-            sal_uInt16              nKeyModifier;
-            TableControlAction  eAction;
-        }
-        static const aKnownActions[] = {
-            { KEY_DOWN,     0,          TableControlAction::cursorDown },
-            { KEY_UP,       0,          TableControlAction::cursorUp },
-            { KEY_LEFT,     0,          TableControlAction::cursorLeft },
-            { KEY_RIGHT,    0,          TableControlAction::cursorRight },
-            { KEY_HOME,     0,          TableControlAction::cursorToLineStart 
},
-            { KEY_END,      0,          TableControlAction::cursorToLineEnd },
-            { KEY_PAGEUP,   0,          TableControlAction::cursorPageUp },
-            { KEY_PAGEDOWN, 0,          TableControlAction::cursorPageDown },
-            { KEY_PAGEUP,   KEY_MOD1,   TableControlAction::cursorToFirstLine 
},
-            { KEY_PAGEDOWN, KEY_MOD1,   TableControlAction::cursorToLastLine },
-            { KEY_HOME,     KEY_MOD1,   TableControlAction::cursorTopLeft },
-            { KEY_END,      KEY_MOD1,   TableControlAction::cursorBottomRight 
},
-            { KEY_SPACE,    KEY_MOD1,   TableControlAction::cursorSelectRow },
-            { KEY_UP,       KEY_SHIFT,  TableControlAction::cursorSelectRowUp 
},
-            { KEY_DOWN,     KEY_SHIFT,  
TableControlAction::cursorSelectRowDown },
-            { KEY_END,      KEY_SHIFT,  
TableControlAction::cursorSelectRowAreaBottom },
-            { KEY_HOME,     KEY_SHIFT,  
TableControlAction::cursorSelectRowAreaTop }
-        };
-        for (const ActionMapEntry& rAction : aKnownActions)
-        {
-            if ( ( rAction.nKeyCode == nKeyCode ) && ( rAction.nKeyModifier == 
rKeyCode.GetModifier() ) )
-            {
-                bHandled = _rControl.dispatchAction( rAction.eAction );
-                break;
-            }
-        }
-
-        return bHandled;
-    }
-
 } // namespace svt::table
 
 
diff --git a/toolkit/source/controls/table/tablecontrol.cxx 
b/toolkit/source/controls/table/tablecontrol.cxx
index bde7d9788126..c5b5ef1c6b78 100644
--- a/toolkit/source/controls/table/tablecontrol.cxx
+++ b/toolkit/source/controls/table/tablecontrol.cxx
@@ -96,7 +96,48 @@ namespace svt::table
 
     void TableControl::KeyInput( const KeyEvent& rKEvt )
     {
-        if (!m_pImpl || !DefaultInputHandler::KeyInput(*m_pImpl, rKEvt))
+        bool bHandled = false;
+        if (m_pImpl)
+        {
+            const vcl::KeyCode& rKeyCode = rKEvt.GetKeyCode();
+            sal_uInt16 nKeyCode = rKeyCode.GetCode();
+
+            struct ActionMapEntry
+            {
+                sal_uInt16 nKeyCode;
+                sal_uInt16 nKeyModifier;
+                TableControlAction eAction;
+            }
+            static const aKnownActions[] = {
+                      { KEY_DOWN,     0,          
TableControlAction::cursorDown },
+                      { KEY_UP,       0,          TableControlAction::cursorUp 
},
+                      { KEY_LEFT,     0,          
TableControlAction::cursorLeft },
+                      { KEY_RIGHT,    0,          
TableControlAction::cursorRight },
+                      { KEY_HOME,     0,          
TableControlAction::cursorToLineStart },
+                      { KEY_END,      0,          
TableControlAction::cursorToLineEnd },
+                      { KEY_PAGEUP,   0,          
TableControlAction::cursorPageUp },
+                      { KEY_PAGEDOWN, 0,          
TableControlAction::cursorPageDown },
+                      { KEY_PAGEUP,   KEY_MOD1,   
TableControlAction::cursorToFirstLine },
+                      { KEY_PAGEDOWN, KEY_MOD1,   
TableControlAction::cursorToLastLine },
+                      { KEY_HOME,     KEY_MOD1,   
TableControlAction::cursorTopLeft },
+                      { KEY_END,      KEY_MOD1,   
TableControlAction::cursorBottomRight },
+                      { KEY_SPACE,    KEY_MOD1,   
TableControlAction::cursorSelectRow },
+                      { KEY_UP,       KEY_SHIFT,  
TableControlAction::cursorSelectRowUp },
+                      { KEY_DOWN,     KEY_SHIFT,  
TableControlAction::cursorSelectRowDown },
+                      { KEY_END,      KEY_SHIFT,  
TableControlAction::cursorSelectRowAreaBottom },
+                      { KEY_HOME,     KEY_SHIFT,  
TableControlAction::cursorSelectRowAreaTop }
+                  };
+            for (const ActionMapEntry& rAction : aKnownActions)
+            {
+                if ((rAction.nKeyCode == nKeyCode) && (rAction.nKeyModifier == 
rKeyCode.GetModifier()))
+                {
+                    bHandled = m_pImpl->dispatchAction(rAction.eAction);
+                    break;
+                }
+            }
+        }
+
+        if (!bHandled)
             Control::KeyInput( rKEvt );
         else
         {
diff --git a/toolkit/source/controls/table/tablecontrol_impl.hxx 
b/toolkit/source/controls/table/tablecontrol_impl.hxx
index db17ef85fdfe..a2fc6ec873d7 100644
--- a/toolkit/source/controls/table/tablecontrol_impl.hxx
+++ b/toolkit/source/controls/table/tablecontrol_impl.hxx
@@ -244,7 +244,19 @@ namespace svt::table
         // ITableControl
         virtual void                hideCursor() override;
         virtual void                showCursor() override;
-        virtual bool                dispatchAction( TableControlAction 
_eAction ) override;
+
+        /** dispatches an action to the table control
+
+            @return
+                <TRUE/> if the action could be dispatched successfully, 
<FALSE/> otherwise. Usual
+                failure conditions include some other instance vetoing the 
action, or impossibility
+                to execute the action at all (for instance moving up one row 
when already positioned
+                on the very first row).
+
+            @see TableControlAction
+        */
+        virtual bool                dispatchAction(TableControlAction 
_eAction);
+
         virtual SelectionEngine*    getSelEngine() override;
         virtual PTableModel         getModel() const override;
         virtual ColPos              getCurrentColumn() const override;
commit 57906dde339a71eee87437ae2d11c7474c03befd
Author:     Michael Weghorn <m.wegh...@posteo.de>
AuthorDate: Thu Jan 23 14:37:07 2025 +0100
Commit:     Michael Weghorn <m.wegh...@posteo.de>
CommitDate: Fri Jan 24 07:37:43 2025 +0100

    tdf#164783 toolkit a11y: Only send event for current cell if there's one
    
    TableControl::commitCellEventIfAccessibleAlive sends an event
    on the currently selected/active cell. So only call it in
    SVTXGridControl::ProcessWindowEvent when there is one.
    
    Use TableControl::GetCurrentRow and TableControl::GetCurrentColumn
    to check that, which return a special value (of -2) for the case there
    is no active cell.
    
    For TableControl::GetCurrentRow:
    
            /** retrieves the current row
    
                The current row is the one which contains the active cell.
    
                @return
                    the row index of the active cell, or ->ROW_INVALID
                    if there is no active cell, e.g. because the table does
                    not contain any rows or columns.
            */
            sal_Int32 GetCurrentRow() const override;
    
    The previous check whether the table has any rows was insufficient
    and resulted in an invalid attempt to access vector elements at
    negative indices.
    
    For the tdf#164783 scenario:
    
        
/usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/debug/vector:508:
        In function:
            reference
            
std::vector<rtl::Reference<accessibility::AccessibleGridControlTableCell>>::operator[](size_type)
            [_Tp = 
rtl::Reference<accessibility::AccessibleGridControlTableCell>,
            _Allocator =
            
std::allocator<rtl::Reference<accessibility::AccessibleGridControlTableCell>>]
    
        Error: attempt to subscript container with out-of-bounds index -6, but
        container only holds 60 elements.
    
        Objects involved in the operation:
            sequence "this" @ 0x5638c74e2350 {
              type = 
std::debug::vector<rtl::Reference<accessibility::AccessibleGridControlTableCell>,
 std::allocator<rtl::Reference<accessibility::AccessibleGridControlTableCell> > 
>;
            }
        
/usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/debug/vector:508:
        In function:
            reference
            
std::vector<rtl::Reference<accessibility::AccessibleGridControlTableCell>>::operator[](size_type)
            [_Tp = 
rtl::Reference<accessibility::AccessibleGridControlTableCell>,
            _Allocator =
            
std::allocator<rtl::Reference<accessibility::AccessibleGridControlTableCell>>]
    
        Error: attempt to subscript container with out-of-bounds index -6, but
        container only holds 60 elements.
    
        Objects involved in the operation:
            sequence "this" @ 0x5638c74e2350 {
              type = 
std::debug::vector<rtl::Reference<accessibility::AccessibleGridControlTableCell>,
 std::allocator<rtl::Reference<accessibility::AccessibleGridControlTableCell> > 
>;
            }
            sequence "this" @ 0x5638c74e2350 {
              type = 
std::debug::vector<rtl::Reference<accessibility::AccessibleGridControlTableCell>,
 std::allocator<rtl::Reference<accessibility::AccessibleGridControlTableCell> > 
>;
            }
    
        Fatal exception: Signal 6
        Stack:
        #0 sal::backtrace_get(unsigned int) at 
.../libreoffice/sal/osl/unx/backtraceapi.cxx:42
        #1 (anonymous namespace)::printStack(int) at 
.../libreoffice/sal/osl/unx/signal.cxx:289
        #2 (anonymous namespace)::callSystemHandler(int, siginfo_t*, void*) at 
.../libreoffice/sal/osl/unx/signal.cxx:330
        #3 (anonymous namespace)::signalHandlerFunction(int, siginfo_t*, void*) 
at .../libreoffice/sal/osl/unx/signal.cxx:427
        #4 /lib/x86_64-linux-gnu/libc.so.6(+0x3fda0) [0x7f7544649da0]
        #5 __pthread_kill_implementation at ./nptl/pthread_kill.c:44 
(discriminator 1)
        #6 raise at ./signal/../sysdeps/posix/raise.c:27
        #7 abort at ./stdlib/abort.c:81
        #8 std::__throw_bad_exception() in /lib/x86_64-linux-gnu/libstdc++.so.6
        #9 
std::__debug::vector<rtl::Reference<accessibility::AccessibleGridControlTableCell>,
 
std::allocator<rtl::Reference<accessibility::AccessibleGridControlTableCell>>>::operator[](unsigned
 long) at 
/usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/debug/vector:508
        #10 accessibility::AccessibleGridControlTable::getAccessibleChild(long) 
at .../libreoffice/vcl/source/accessibility/AccessibleGridControlTable.cxx:66
        #11 accessibility::AccessibleGridControlTable::getAccessibleCellAt(int, 
int) at 
.../libreoffice/vcl/source/accessibility/AccessibleGridControlTable.cxx:191
        #12 accessibility::AccessibleGridControl::commitCellEvent(short, 
com::sun::star::uno::Any const&, com::sun::star::uno::Any const&) at 
.../libreoffice/vcl/source/accessibility/AccessibleGridControl.cxx:272
        #13 accessibility::AccessibleGridControlAccess::commitCellEvent(short, 
com::sun::star::uno::Any const&, com::sun::star::uno::Any const&) at 
.../libreoffice/vcl/inc/accessibility/AccessibleGridControl.hxx:197
        #14 svt::table::TableControl_Impl::commitCellEvent(short, 
com::sun::star::uno::Any const&, com::sun::star::uno::Any const&) at 
.../libreoffice/toolkit/source/controls/table/tablecontrol_impl.cxx:2304
        #15 svt::table::TableControl::commitCellEventIfAccessibleAlive(short, 
com::sun::star::uno::Any const&, com::sun::star::uno::Any const&) at 
.../libreoffice/toolkit/source/controls/table/tablecontrol.cxx:470
        #16 SVTXGridControl::ProcessWindowEvent(VclWindowEvent const&) at 
.../libreoffice/toolkit/source/controls/svtxgridcontrol.cxx:823
        #17 VCLXWindow::WindowEventListener(VclWindowEvent&) at 
.../libreoffice/toolkit/source/awt/vclxwindow.cxx:390
        #18 VCLXWindow::LinkStubWindowEventListener(void*, VclWindowEvent&) at 
.../libreoffice/toolkit/source/awt/vclxwindow.cxx:383
        #19 Link<VclWindowEvent&, void>::Call(VclWindowEvent&) const at 
.../libreoffice/include/tools/link.hxx:101
        #20 vcl::Window::CallEventListeners(VclEventId, void*) at 
.../libreoffice/vcl/source/window/event.cxx:262
        #21 Control::CallEventListeners(VclEventId, void*) at 
.../libreoffice/vcl/source/control/ctrl.cxx:298
        #22 Control::ImplCallEventListenersAndHandler(VclEventId, 
std::function<void ()> const&) at 
.../libreoffice/vcl/source/control/ctrl.cxx:305
        #23 Control::EventNotify(NotifyEvent&) at 
.../libreoffice/vcl/source/control/ctrl.cxx:247
        #24 vcl::Window::CompatNotify(NotifyEvent&) at 
.../libreoffice/vcl/source/window/window.cxx:3943
        #25 vcl::Window::LoseFocus() at 
.../libreoffice/vcl/source/window/window.cxx:1861
        #26 svt::table::TableControl::LoseFocus() at 
.../libreoffice/toolkit/source/controls/table/tablecontrol.cxx:94
        #27 vcl::Window::CompatLoseFocus() at 
.../libreoffice/vcl/source/window/window.cxx:3912
        #28 vcl::Window::ImplAsyncFocusHdl(void*) at 
.../libreoffice/vcl/source/window/winproc.cxx:2127
        #29 vcl::Window::LinkStubImplAsyncFocusHdl(void*, void*) at 
.../libreoffice/vcl/source/window/winproc.cxx:2033
        #30 Link<void*, void>::Call(void*) const at 
.../libreoffice/include/tools/link.hxx:101
        #31 ImplHandleUserEvent(ImplSVEvent*) at 
.../libreoffice/vcl/source/window/winproc.cxx:2288
        #32 ImplWindowFrameProc(vcl::Window*, SalEvent, void const*) at 
.../libreoffice/vcl/source/window/winproc.cxx:2849
        #33 SalFrame::CallCallback(SalEvent, void const*) const at 
.../libreoffice/vcl/inc/salframe.hxx:311
        #34 SalGenericDisplay::ProcessEvent(SalUserEventList::SalUserEvent) at 
.../libreoffice/vcl/unx/generic/app/gendisp.cxx:67
        #35 SalUserEventList::DispatchUserEvents(bool)::$_0::operator()() const 
at .../libreoffice/vcl/source/app/salusereventlist.cxx:119
        #36 SalUserEventList::DispatchUserEvents(bool) at 
.../libreoffice/vcl/source/app/salusereventlist.cxx:120
        #37 SalGenericDisplay::DispatchInternalEvent(bool) at 
.../libreoffice/vcl/unx/generic/app/gendisp.cxx:51
        #38 call_userEventFn(void*) at 
.../libreoffice/vcl/unx/gtk3/gtkdata.cxx:827
        #39 /lib/x86_64-linux-gnu/libglib-2.0.so.0(+0x5a81f) [0x7f7536f0b81f]
        #40 /lib/x86_64-linux-gnu/libglib-2.0.so.0(+0x5ca57) [0x7f7536f0da57]
        #41 g_main_loop_run in /lib/x86_64-linux-gnu/libglib-2.0.so.0
        ...
    
    Change-Id: Iafed90e6985cf2c05d65be5f74334f58b369d945
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/180661
    Tested-by: Jenkins
    Reviewed-by: Michael Weghorn <m.wegh...@posteo.de>

diff --git a/toolkit/source/controls/svtxgridcontrol.cxx 
b/toolkit/source/controls/svtxgridcontrol.cxx
index 6cd34bef8bca..74036177d8ab 100644
--- a/toolkit/source/controls/svtxgridcontrol.cxx
+++ b/toolkit/source/controls/svtxgridcontrol.cxx
@@ -790,7 +790,7 @@ void SVTXGridControl::ProcessWindowEvent( const 
VclWindowEvent& rVclWindowEvent
         {
             // TODO: this doesn't belong here. It belongs into the 
TableControl/_Impl, so A11Y also
             // works when the control is used outside the UNO context
-            if ( pTable->GetRowCount()>0 )
+            if (pTable->GetCurrentRow() !=  ROW_INVALID && 
pTable->GetCurrentColumn() != COL_INVALID)
             {
                 pTable->commitCellEventIfAccessibleAlive(
                     AccessibleEventId::STATE_CHANGED,
@@ -818,7 +818,7 @@ void SVTXGridControl::ProcessWindowEvent( const 
VclWindowEvent& rVclWindowEvent
         {
             // TODO: this doesn't belong here. It belongs into the 
TableControl/_Impl, so A11Y also
             // works when the control is used outside the UNO context
-            if ( pTable->GetRowCount()>0 )
+            if (pTable->GetCurrentRow() !=  ROW_INVALID && 
pTable->GetCurrentColumn() != COL_INVALID)
             {
                 pTable->commitCellEventIfAccessibleAlive(
                     AccessibleEventId::STATE_CHANGED,

Reply via email to