vcl: interface for WinAPI FlashWindow() function

To improve LibreOffice UX it will be great to have possibility to
signal user on some event did happen, but without capuring focus
and bringing LO to foreground, like it is happenings sometimes. It
can be annoying.

For example, if dialog window is opening slowly and user did switch
to another application, this is used to inform user that there
are some updates in LO window: dialog finally alive.

There are somewhat confusing implementation of this feature: VCL dialog
window became visible and actual Windows window should use
::FlashWindow() are very different in hierarchies, so it is somewhat
challenging to find window to flash or even decide shoud we flash window
or not.

Change-Id: I6ca6706d2dda8902aea273ebe6e318ec9bf4beda
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/158472
Tested-by: Jenkins
Reviewed-by: Samuel Mehrbrodt <samuel.mehrbrodt@allotropia.de>
This commit is contained in:
Vasily Melenchuk 2023-10-25 22:26:14 +03:00 committed by Samuel Mehrbrodt
parent 0b21e2a404
commit 68f55fc9a1
7 changed files with 35 additions and 0 deletions

View file

@ -1119,6 +1119,9 @@ public:
/// Dumps itself and potentially its children to a property tree, to be written easily to JSON.
virtual void DumpAsPropertyTree(tools::JsonWriter&);
virtual void FlashWindow() const {};
/** @name Accessibility
*/
///@{

View file

@ -169,6 +169,8 @@ public:
tools::Rectangle GetMenuRect() const;
virtual Size GetOptimalSize() const override;
virtual void FlashWindow() const override;
};
struct ImplBorderFrameData

View file

@ -211,6 +211,8 @@ public:
virtual void Beep() = 0;
virtual void FlashWindow() const {};
// returns system data (most prominent: window handle)
virtual const SystemEnvData*
GetSystemData() const = 0;

View file

@ -126,6 +126,7 @@ public:
virtual LanguageType GetInputLanguage() override;
virtual void UpdateSettings( AllSettings& rSettings ) override;
virtual void Beep() override;
virtual void FlashWindow() const override;
virtual const SystemEnvData* GetSystemData() const override;
virtual SalPointerState GetPointerState() override;
virtual KeyIndicatorState GetIndicatorState() override;

View file

@ -20,6 +20,7 @@
#include <strings.hrc>
#include <svdata.hxx>
#include <brdwin.hxx>
#include <salframe.hxx>
#include <window.h>
#include <vcl/textrectinfo.hxx>
@ -2000,4 +2001,18 @@ void ImplBorderWindow::queue_resize(StateChangedType eReason)
vcl::Window::queue_resize(eReason);
}
void ImplBorderWindow::FlashWindow() const
{
// We are showing top level window without focus received. Let's flash it
// Use OS features to bring user attention to this window: find topmost one and FlashWindow
vcl::Window* pMyParent = mpWindowImpl->mpParent;
while (pMyParent && pMyParent->mpWindowImpl && pMyParent->mpWindowImpl->mpParent)
{
pMyParent = pMyParent->mpWindowImpl->mpParent;
}
if (pMyParent) {
pMyParent->mpWindowImpl->mpFrame->FlashWindow();
}
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

View file

@ -2322,6 +2322,10 @@ void Window::Show(bool bVisible, ShowFlags nFlags)
ImplFocusToTop( ToTopFlags::NONE, false );
}
if (!HasFocus() && GetParent()) {
GetParent()->FlashWindow();
}
// adjust mpWindowImpl->mbReallyVisible
bRealVisibilityChanged = !mpWindowImpl->mbReallyVisible;
ImplSetReallyVisible();

View file

@ -2993,6 +2993,14 @@ void WinSalFrame::Beep()
MessageBeep( 0 );
}
void WinSalFrame::FlashWindow() const
{
if (GetForegroundWindow() != mhWnd)
{
::FlashWindow(mhWnd, TRUE);
}
}
SalFrame::SalPointerState WinSalFrame::GetPointerState()
{
SalPointerState aState;