vcl/inc/impdel.hxx | 6 ++++ vcl/source/window/window.cxx | 4 ++ vcl/win/window/salframe.cxx | 59 ++++++++++++++++++++++++++----------------- 3 files changed, 46 insertions(+), 23 deletions(-)
New commits: commit a2dd71feb75d93adf0f0daac899e7476f961ec34 Author: Mike Kaganski <[email protected]> AuthorDate: Sat Feb 10 20:01:05 2024 +0600 Commit: Mike Kaganski <[email protected]> CommitDate: Sat Feb 10 16:58:11 2024 +0100 tdf#54169: implement auto-accelerator feature on Windows Change-Id: I219dfc0c8377628c10e5a19232d19260923bf614 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/163215 Tested-by: Mike Kaganski <[email protected]> Reviewed-by: Mike Kaganski <[email protected]> diff --git a/vcl/inc/impdel.hxx b/vcl/inc/impdel.hxx index b387c34a0974..3b9dbb60a45e 100644 --- a/vcl/inc/impdel.hxx +++ b/vcl/inc/impdel.hxx @@ -57,6 +57,12 @@ class DeletionListener if( m_pNotifier ) m_pNotifier->addDel( this ); } + DeletionListener(const DeletionListener& rOther) + : m_pNotifier(rOther.m_pNotifier) + { + if (m_pNotifier) + m_pNotifier->addDel(this); + } ~DeletionListener() { if( m_pNotifier ) diff --git a/vcl/source/window/window.cxx b/vcl/source/window/window.cxx index 85454316acdf..ec3adaca4674 100644 --- a/vcl/source/window/window.cxx +++ b/vcl/source/window/window.cxx @@ -1808,15 +1808,17 @@ void Window::SimulateKeyPress( sal_uInt16 nKeyCode ) const void Window::KeyInput( const KeyEvent& rKEvt ) { +#ifndef _WIN32 // On Windows, dialogs react to accelerators without Alt (tdf#157649) KeyCode cod = rKEvt.GetKeyCode (); - bool autoacc = ImplGetSVData()->maNWFData.mbAutoAccel; // do not respond to accelerators unless Alt or Ctrl is held if (cod.GetCode () >= 0x200 && cod.GetCode () <= 0x219) { + bool autoacc = ImplGetSVData()->maNWFData.mbAutoAccel; if (autoacc && cod.GetModifier () != KEY_MOD2 && !(cod.GetModifier() & KEY_MOD1)) return; } +#endif NotifyEvent aNEvt( NotifyEventType::KEYINPUT, this, &rKEvt ); if ( !CompatNotify( aNEvt ) ) diff --git a/vcl/win/window/salframe.cxx b/vcl/win/window/salframe.cxx index ed8f7fddee7a..313ae0ffcf2d 100644 --- a/vcl/win/window/salframe.cxx +++ b/vcl/win/window/salframe.cxx @@ -301,6 +301,15 @@ static void UpdateDarkMode(HWND hWnd) DwmSetWindowAttribute(hWnd, 20, &bDarkMode, sizeof(bDarkMode)); } +static void UpdateAutoAccel() +{ + BOOL bUnderline = FALSE; + SystemParametersInfoW(SPI_GETKEYBOARDCUES, 0, &bUnderline, 0); + + ImplSVData* pSVData = ImplGetSVData(); + pSVData->maNWFData.mbAutoAccel = !bUnderline; +} + SalFrame* ImplSalCreateFrame( WinSalInstance* pInst, HWND hWndParent, SalFrameStyleFlags nSalFrameStyle ) { @@ -3578,7 +3587,7 @@ static bool HandleAltNumPadCode(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lPar if (!(keyFlags & KF_REPEAT)) state.clear(); state.started = true; - return true; + return false; // This must be processed further - e.g., to show accelerators } if (!state.started) @@ -3637,8 +3646,6 @@ static bool ImplHandleKeyMsg( HWND hWnd, UINT nMsg, static WPARAM nDeadChar = 0; static WPARAM nLastVKChar = 0; static sal_uInt16 nLastChar = 0; - static ModKeyFlags nLastModKeyCode = ModKeyFlags::NONE; - static bool bWaitForModKeyRelease = false; sal_uInt16 nRepeat = LOWORD( lParam ); if (nRepeat) --nRepeat; @@ -3774,14 +3781,11 @@ static bool ImplHandleKeyMsg( HWND hWnd, UINT nMsg, // MCD, 2003-01-13, Support for WM_UNICHAR & Keyman 6.0; addition ends else { + static ModKeyFlags nLastModKeyCode = ModKeyFlags::NONE; + // for shift, control and menu we issue a KeyModChange event if ( (wParam == VK_SHIFT) || (wParam == VK_CONTROL) || (wParam == VK_MENU) ) { - SalKeyModEvent aModEvt; - aModEvt.mbDown = false; // auto-accelerator feature not supported here. - aModEvt.mnCode = nModCode; - aModEvt.mnModKeyCode = ModKeyFlags::NONE; // no command events will be sent if this member is 0 - ModKeyFlags tmpCode = ModKeyFlags::NONE; if( GetKeyState( VK_LSHIFT ) & 0x8000 ) tmpCode |= ModKeyFlags::LeftShift; @@ -3796,22 +3800,16 @@ static bool ImplHandleKeyMsg( HWND hWnd, UINT nMsg, if( GetKeyState( VK_RMENU ) & 0x8000 ) tmpCode |= ModKeyFlags::RightMod2; - if( tmpCode < nLastModKeyCode ) + if (tmpCode != nLastModKeyCode) { - aModEvt.mnModKeyCode = nLastModKeyCode; - nLastModKeyCode = ModKeyFlags::NONE; - bWaitForModKeyRelease = true; + SalKeyModEvent aModEvt; + aModEvt.mbDown = nMsg == WM_KEYDOWN || nMsg == WM_SYSKEYDOWN; + aModEvt.mnCode = nModCode; + aModEvt.mnModKeyCode = tmpCode < nLastModKeyCode ? nLastModKeyCode : tmpCode; + nLastModKeyCode = tmpCode; + return pFrame->CallCallback(SalEvent::KeyModChange, &aModEvt); } - else - { - if( !bWaitForModKeyRelease ) - nLastModKeyCode = tmpCode; - } - - if( tmpCode == ModKeyFlags::NONE ) - bWaitForModKeyRelease = false; - - return pFrame->CallCallback( SalEvent::KeyModChange, &aModEvt ); + return false; } else { @@ -3822,6 +3820,21 @@ static bool ImplHandleKeyMsg( HWND hWnd, UINT nMsg, UINT nCharMsg = WM_CHAR; bool bKeyUp = (nMsg == WM_KEYUP) || (nMsg == WM_SYSKEYUP); + comphelper::ScopeGuard aEndModKeyCodes( + [nModCode, pFrame, listener = vcl::DeletionListener(pFrame)] + { + if (listener.isDeleted()) + return; + // Send SalEvent::KeyModChange, to make sure that this window ends special mode + // (e.g., hides mnemonics if auto-accelerator feature is active) + SalKeyModEvent aModEvt; + aModEvt.mbDown = false; + aModEvt.mnCode = nModCode; + aModEvt.mnModKeyCode = nLastModKeyCode; + pFrame->CallCallback(SalEvent::KeyModChange, &aModEvt); + }); + if (nLastModKeyCode == ModKeyFlags::NONE) + aEndModKeyCodes.dismiss(); nLastModKeyCode = ModKeyFlags::NONE; // make sure no modkey messages are sent if they belong to a hotkey (see above) aKeyEvt.mnCharCode = 0; aKeyEvt.mnCode = ImplSalGetKeyCode( wParam ); @@ -4376,6 +4389,7 @@ static void ImplHandleSettingsChangeMsg(HWND hWnd, UINT nMsg, WPARAM /*wParam*/, } aSalShlData.mnWheelScrollLines = ImplSalGetWheelScrollLines(); aSalShlData.mnWheelScrollChars = ImplSalGetWheelScrollChars(); + UpdateAutoAccel(); UpdateDarkMode(hWnd); GetSalData()->mbThemeChanged = true; } @@ -5782,6 +5796,7 @@ static LRESULT CALLBACK SalFrameWndProc( HWND hWnd, UINT nMsg, WPARAM wParam, LP { SetWindowPtr( hWnd, pFrame ); + UpdateAutoAccel(); UpdateDarkMode(hWnd); // Set HWND already here, as data might be used already
