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 ab0d6e455b7b67bd9e9c719dc4e564ee52e3b5e8
Author:     Vasily Melenchuk <vasily.melenc...@cib.de>
AuthorDate: Wed Oct 25 22:26:14 2023 +0300
Commit:     Thorsten Behrens <thorsten.behr...@allotropia.de>
CommitDate: Tue Mar 12 18:45:08 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>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/164719
    Tested-by: Thorsten Behrens <thorsten.behr...@allotropia.de>
    Reviewed-by: Thorsten Behrens <thorsten.behr...@allotropia.de>

diff --git a/include/vcl/window.hxx b/include/vcl/window.hxx
index d23b34e397dd..1c55dea078b5 100644
--- a/include/vcl/window.hxx
+++ b/include/vcl/window.hxx
@@ -1215,6 +1215,9 @@ public:
     /// Same as MouseMove(), but coordinates are in logic unit. used for LOK
     virtual void LogicMouseMove(const MouseEvent&) {};
 
+
+    virtual void FlashWindow() const {};
+
     /** @name Accessibility
      */
     ///@{
diff --git a/vcl/inc/brdwin.hxx b/vcl/inc/brdwin.hxx
index 0510006fa3ea..057415ce4a7c 100644
--- a/vcl/inc/brdwin.hxx
+++ b/vcl/inc/brdwin.hxx
@@ -171,6 +171,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 4b540d61ca0e..74d4946eb262 100644
--- a/vcl/inc/salframe.hxx
+++ b/vcl/inc/salframe.hxx
@@ -208,6 +208,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 25c6819bb7e2..f7bf988de410 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 1b436b544700..f6d06f5073ba 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>
@@ -2070,4 +2071,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 9a5a6cde533b..d10674274cff 100644
--- a/vcl/source/window/window.cxx
+++ b/vcl/source/window/window.cxx
@@ -2277,6 +2277,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 ea55cae92a89..c3f86d5cd1bb 100644
--- a/vcl/win/window/salframe.cxx
+++ b/vcl/win/window/salframe.cxx
@@ -2853,6 +2853,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