framework/source/inc/loadenv/loadenv.hxx |   11 ++++++++++
 framework/source/loadenv/loadenv.cxx     |   32 ++++++++++++-------------------
 sd/source/ui/inc/DrawViewShell.hxx       |    5 ++++
 sd/source/ui/view/drviews1.cxx           |   19 ++++++++++++------
 4 files changed, 42 insertions(+), 25 deletions(-)

New commits:
commit 42d197ef301db68e56f7e45b6e36ace5fae04b4d
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Sun Sep 4 13:39:27 2022 +0300
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Sun Sep 4 19:44:49 2022 +0200

    tdf#150773: Avoid bringing loading files to front several times
    
    The change attempts to establish this logic:
    1. Honor the ForceFocusAndToFront setting uniformly: previously, it
       was ignored when reusing existing windows (opening in Start Center,
       in place of an empty document, or trying to open an already opened
       document);
    2. When ForceFocusAndToFront is set, try to activate the window as
       early as possible (before loading begind), as a feedback to user,
       and also to avoid situations when activation would be impossible
       later (e.g., there is a timespan on Windows, during which entitled
       applications can bring themselves to foreground; a lengthy loading
       process can exceed that time);
    3. If activated once, do not activate second time after loading ends,
       to avoid nagging users who deliberately switched to other tasks.
    
    Explicit calls to impl_makeFrameWindowVisible were removed from
    impl_searchAlreadyLoaded and impl_isFrameAlreadyUsedForLoading,
    because those functions are called from impl_loadContent, which makes
    sure that they are followed by a call to impl_makeFrameWindowVisible
    (either in impl_setResult -> impl_reactForLoadingState, or directly).
    
    A fix to tdf#83773 was adjusted; I checked that the bug doesn't
    reappear after that.
    
    Change-Id: I4bdcf978d43016d1e8979adf2fdf108a37f6ba2d
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/139362
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>

diff --git a/framework/source/inc/loadenv/loadenv.hxx 
b/framework/source/inc/loadenv/loadenv.hxx
index 351d39b94b4e..baad8fac9b7f 100644
--- a/framework/source/inc/loadenv/loadenv.hxx
+++ b/framework/source/inc/loadenv/loadenv.hxx
@@ -179,6 +179,12 @@ private:
      */
     bool m_bLoaded;
 
+    /** @short  If we already brought it to front; do not do that again
+                (the user could switch elsewhere after the first activation,
+                and we shouldn't nag them again).
+     */
+    bool m_bFocusedAndToFront = false;
+
     /** @short      holds an XActionLock on the internal used task member.
 
         @seealso    m_xTargetFrame
@@ -533,6 +539,11 @@ private:
                 loading the document.
      */
     bool impl_filterHasInteractiveDialog() const;
+
+    /** @short  checks if this should bring to front and get focus on load,
+                according to user settings and to the load flags.
+     */
+    bool shouldFocusAndToFront() const;
 };
 
 } // namespace framework
diff --git a/framework/source/loadenv/loadenv.cxx 
b/framework/source/loadenv/loadenv.cxx
index f8d0176b6276..0cd8b0b38330 100644
--- a/framework/source/loadenv/loadenv.cxx
+++ b/framework/source/loadenv/loadenv.cxx
@@ -1119,7 +1119,10 @@ bool LoadEnv::impl_loadContent()
             xHandler->initialize(aArguments);
             //show the frame as early as possible to make it the parent of any 
message dialogs
             if (!impl_filterHasInteractiveDialog())
-                impl_makeFrameWindowVisible(xWindow, false);
+            {
+                impl_makeFrameWindowVisible(xWindow, shouldFocusAndToFront());
+                m_bFocusedAndToFront = true; // no need to ask 
shouldFocusAndToFront second time
+            }
         }
     }
 
@@ -1408,9 +1411,6 @@ css::uno::Reference< css::frame::XFrame > 
LoadEnv::impl_searchAlreadyLoaded()
         // if an optional jumpmark is given too.
         if (!m_aURL.Mark.isEmpty())
             impl_jumpToMark(xResult, m_aURL);
-
-        // bring it to front and make sure it's visible...
-        impl_makeFrameWindowVisible(xResult->getContainerWindow(), true);
     }
 
     return xResult;
@@ -1448,8 +1448,6 @@ css::uno::Reference< css::frame::XFrame > 
LoadEnv::impl_searchRecycleTarget()
     {
         if 
(!impl_isFrameAlreadyUsedForLoading(aTasksAnalyzer.m_xBackingComponent))
         {
-            // bring it to front...
-            
impl_makeFrameWindowVisible(aTasksAnalyzer.m_xBackingComponent->getContainerWindow(),
 true);
             m_bReactivateControllerOnError = true;
             return aTasksAnalyzer.m_xBackingComponent;
         }
@@ -1562,9 +1560,6 @@ css::uno::Reference< css::frame::XFrame > 
LoadEnv::impl_searchRecycleTarget()
     }
     // <- SAFE ..................................
 
-    // bring it to front ...
-    impl_makeFrameWindowVisible(xTask->getContainerWindow(), true);
-
     return xTask;
 }
 
@@ -1596,7 +1591,7 @@ void LoadEnv::impl_reactForLoadingState()
         {
             // show frame ... if it's not still visible ...
             // But do nothing if it's already visible!
-            impl_makeFrameWindowVisible(xWindow, false);
+            impl_makeFrameWindowVisible(xWindow, !m_bFocusedAndToFront && 
shouldFocusAndToFront());
         }
 
         // Note: Only if an existing property "FrameName" is given by this 
media descriptor,
@@ -1683,6 +1678,14 @@ void LoadEnv::impl_reactForLoadingState()
     // <- SAFE ----------------------------------
 }
 
+bool LoadEnv::shouldFocusAndToFront() const
+{
+    bool const preview(
+        
m_lMediaDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_PREVIEW,
 false));
+    return !preview
+           && 
officecfg::Office::Common::View::NewDocumentHandling::ForceFocusAndToFront::get();
+}
+
 void LoadEnv::impl_makeFrameWindowVisible(const css::uno::Reference< 
css::awt::XWindow >& xWindow      ,
                                                 bool bForceToFront)
 {
@@ -1691,15 +1694,6 @@ void LoadEnv::impl_makeFrameWindowVisible(const 
css::uno::Reference< css::awt::X
     if ( !pWindow )
         return;
 
-    if (!bForceToFront)
-    {
-        bool const preview(m_lMediaDescriptor.getUnpackedValueOrDefault(
-            utl::MediaDescriptor::PROP_PREVIEW, false));
-        bForceToFront
-            = !preview
-              && 
officecfg::Office::Common::View::NewDocumentHandling::ForceFocusAndToFront::get();
-    }
-
     if (pWindow->IsVisible() && bForceToFront)
         pWindow->ToTop( ToTopFlags::RestoreWhenMin | 
ToTopFlags::ForegroundTask );
     else
diff --git a/sd/source/ui/inc/DrawViewShell.hxx 
b/sd/source/ui/inc/DrawViewShell.hxx
index c56a0f33e604..e75570a79638 100644
--- a/sd/source/ui/inc/DrawViewShell.hxx
+++ b/sd/source/ui/inc/DrawViewShell.hxx
@@ -414,6 +414,11 @@ protected:
     void            GetMenuStateSel(SfxItemSet& rSet);
 
 private:
+    /** Prevents grabbing focus while loading - see tdf#83773 that intruduced
+        the grabbing, and tdf#150773 that needs grabbing disabled on loading
+    */
+    bool mbFirstTimeActivation = true;
+
     /** This flag controls whether the layer mode is active, i.e. the layer
         dialog is visible.
     */
diff --git a/sd/source/ui/view/drviews1.cxx b/sd/source/ui/view/drviews1.cxx
index 9f372f67e320..64440617e611 100644
--- a/sd/source/ui/view/drviews1.cxx
+++ b/sd/source/ui/view/drviews1.cxx
@@ -79,13 +79,20 @@ void DrawViewShell::Activate(bool bIsMDIActivate)
 {
     ViewShell::Activate(bIsMDIActivate);
 
-    // When the mode is switched to normal the main view shell grabs focus.
-    // This is done for getting cut/copy/paste commands on slides in the left
-    // pane (slide sorter view shell) to work properly.
-    SfxShell* pTopViewShell = 
this->GetViewShellBase().GetViewShellManager()->GetTopViewShell();
-    if (pTopViewShell && pTopViewShell == this)
+    // tdf#150773: do not grab focus on loading
+    if (mbFirstTimeActivation)
+        mbFirstTimeActivation = false;
+    else
     {
-        this->GetActiveWindow()->GrabFocus();
+
+        // When the mode is switched to normal the main view shell grabs focus.
+        // This is done for getting cut/copy/paste commands on slides in the 
left
+        // pane (slide sorter view shell) to work properly.
+        SfxShell* pTopViewShell = 
GetViewShellBase().GetViewShellManager()->GetTopViewShell();
+        if (pTopViewShell == this)
+        {
+            GetActiveWindow()->GrabFocus();
+        }
     }
 }
 

Reply via email to