include/vcl/window.hxx       |    3 +++
 vcl/inc/brdwin.hxx           |    2 ++
 vcl/inc/salframe.hxx         |    2 ++
 vcl/inc/win/salframe.h       |    1 +
 vcl/source/window/brdwin.cxx |   15 +++++++++++++++
 vcl/source/window/window.cxx |    4 ++++
 vcl/win/window/salframe.cxx  |    8 ++++++++
 7 files changed, 35 insertions(+)

New commits:
commit 68f55fc9a1aa8c0f403761e39e7531ae298ea79e
Author:     Vasily Melenchuk <vasily.melenc...@cib.de>
AuthorDate: Wed Oct 25 22:26:14 2023 +0300
Commit:     Samuel Mehrbrodt <samuel.mehrbr...@allotropia.de>
CommitDate: Mon Mar 4 15:30:22 2024 +0100

    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.mehrbr...@allotropia.de>

diff --git a/include/vcl/window.hxx b/include/vcl/window.hxx
index 74f1d395e9ad..f451d6f3038b 100644
--- a/include/vcl/window.hxx
+++ b/include/vcl/window.hxx
@@ -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
      */
     ///@{
diff --git a/vcl/inc/brdwin.hxx b/vcl/inc/brdwin.hxx
index f9c8a8edb894..dbaa52ed02b2 100644
--- a/vcl/inc/brdwin.hxx
+++ b/vcl/inc/brdwin.hxx
@@ -169,6 +169,8 @@ public:
     tools::Rectangle               GetMenuRect() const;
 
     virtual Size            GetOptimalSize() const override;
+
+    virtual void FlashWindow() const override;
 };
 
 struct ImplBorderFrameData
diff --git a/vcl/inc/salframe.hxx b/vcl/inc/salframe.hxx
index f25f8de92777..a2ce50202b92 100644
--- a/vcl/inc/salframe.hxx
+++ b/vcl/inc/salframe.hxx
@@ -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;
diff --git a/vcl/inc/win/salframe.h b/vcl/inc/win/salframe.h
index de72c089b57b..b9ddea89476a 100644
--- a/vcl/inc/win/salframe.h
+++ b/vcl/inc/win/salframe.h
@@ -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;
diff --git a/vcl/source/window/brdwin.cxx b/vcl/source/window/brdwin.cxx
index e7b569364021..d1de4daffac5 100644
--- a/vcl/source/window/brdwin.cxx
+++ b/vcl/source/window/brdwin.cxx
@@ -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: */
diff --git a/vcl/source/window/window.cxx b/vcl/source/window/window.cxx
index 1e661c4151d1..62bc5029f84d 100644
--- a/vcl/source/window/window.cxx
+++ b/vcl/source/window/window.cxx
@@ -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();
diff --git a/vcl/win/window/salframe.cxx b/vcl/win/window/salframe.cxx
index 81dcf341e60d..ab20e2411e42 100644
--- a/vcl/win/window/salframe.cxx
+++ b/vcl/win/window/salframe.cxx
@@ -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;

Reply via email to