Repository: pyinstaller/pyinstaller

Issue:
Minimize-able/Hide-able Splash 
**Is your feature request related to a problem? Please describe.**
The splash screen seems to be Always on Top. In case program startup takes a long time, it is a bit annoying to have a splash in the middle of everything. Also no icon in the taskbar to minimize.

**Describe the solution you'd like**
Make the splash behave like a normal window that can be hidden by other windows.


Discussion:
Hmm, I suppose we could make the [always-on-top behavior](https://github.com/pyinstaller/pyinstaller/blob/56b2dd51d30103e9200496c0ec5b5a11e7bf546e/PyInstaller/building/splash_templates.py#L173) an option (or just disable it altogether).

To make the splash screen window-like, we'd need to disable [this](https://github.com/pyinstaller/pyinstaller/blob/56b2dd51d30103e9200496c0ec5b5a11e7bf546e/PyInstaller/building/splash_templates.py#L171), but I don't think that's a good idea because it will give user an option to close the window, which will likely lead to undesired side effects (i.e., exceptions when trying to modify or close the splash screen in python code).
Disabling the always on top flag sounds best to me. It feels too minor to warrant making it configurable.
That said, disabling the `-topmost` flag doesn't appear to make any difference.
> That said, disabling the `-topmost` flag doesn't appear to make any difference.

Hmm, it indeed seems to make no difference on linux, but it seems to do on Windows.
Looks like on linux, we can use `-type splash` [attribute](https://wiki.tcl-lang.org/page/wm+attributes), while disabling `overridedirect`:
```
# Set position and mode of the window
#wm overrideredirect . 1
wm geometry         . +${x_position}+${y_position}
#wm attributes       . -topmost 0
wm attributes         . -type splash
```

Resolving patch:
diff --git a/PyInstaller/building/splash.py b/PyInstaller/building/splash.py
--- a/PyInstaller/building/splash.py
+++ b/PyInstaller/building/splash.py
@@ -120,6 +120,11 @@ def __init__(self, image_file, binaries, datas, **kwargs):
             resized to fit the maximum width (to keep the original aspect ratio). This option can be disabled by
             setting it to None. Default: (760, 480)
         :type max_img_size: Tuple[int, int]
+        :keyword always_on_top:
+            Force the splashscreen to be always on top of other windows. If disabled, other windows (e.g., from other
+            applications) can cover the splash screen by user bringing them to front. This might be useful for
+            frozen applications with long startup times. Default: True
+        :type always_on_top: bool
         """
         from ..config import CONF
         Target.__init__(self)
@@ -152,6 +157,9 @@ def __init__(self, image_file, binaries, datas, **kwargs):
         self.text_color = kwargs.get("text_color", "black")
         self.text_default = kwargs.get("text_default", "Initializing")
 
+        # always-on-top behavior
+        self.always_on_top = kwargs.get("always_on_top", True)
+
         # Save the generated file separately so that it is not necessary to generate the data again and again
         root = os.path.splitext(self.tocfilename)[0]
         if self.name is None:
@@ -244,6 +252,7 @@ def _filter(_item):
         ('text_font', _check_guts_eq),
         ('text_color', _check_guts_eq),
         ('text_default', _check_guts_eq),
+        ('always_on_top', _check_guts_eq),
         ('full_tk', _check_guts_eq),
         ('minify_script', _check_guts_eq),
         ('rundir', _check_guts_eq),
@@ -416,7 +425,7 @@ def generate_script(self):
                 'font_size': self.text_size,
                 'default_text': self.text_default,
             })
-        script = splash_templates.build_script(text_options=d)
+        script = splash_templates.build_script(text_options=d, always_on_top=self.always_on_top)
 
         if self.minify_script:
             # Remove any documentation, empty lines and unnecessary spaces
diff --git a/PyInstaller/building/splash_templates.py b/PyInstaller/building/splash_templates.py
--- a/PyInstaller/building/splash_templates.py
+++ b/PyInstaller/building/splash_templates.py
@@ -162,21 +162,46 @@
     # For Linux there is no common way to create a transparent window
     transparent_setup = r""
 
-align_windows = r"""
-# Position all widget in the window
+pack_widgets = r"""
+# Position all widgets in the window
 pack .root
 grid .root.canvas   -column 0 -row 0 -columnspan 1 -rowspan 2
+"""
 
-# Set position and mode of the window
+# Enable always-on-top behavior, by setting overrideredirect and the topmost attribute.
+position_window_on_top = r"""
+# Set position and mode of the window - always-on-top behavior
 wm overrideredirect . 1
 wm geometry         . +${x_position}+${y_position}
 wm attributes       . -topmost 1
+"""
 
+# Disable always-on-top behavior
+if is_win or is_cygwin or is_darwin:
+    # On Windows, we disable the always-on-top behavior while still setting overrideredirect
+    # (to disable window decorations), but set topmost attribute to 0.
+    position_window = r"""
+# Set position and mode of the window
+wm overrideredirect . 1
+wm geometry         . +${x_position}+${y_position}
+wm attributes       . -topmost 0
+"""
+else:
+    # On Linux, we must not use overrideredirect; instead, we set X11-specific type attribute to splash,
+    # which lets the window manager to properly handle the splash screen (without window decorations
+    # but allowing other windows to be brought to front).
+    position_window = r"""
+# Set position and mode of the window
+wm geometry         . +${x_position}+${y_position}
+wm attributes       . -type splash
+"""
+
+raise_window = r"""
 raise .
 """
 
 
-def build_script(text_options=None):
+def build_script(text_options=None, always_on_top=False):
     """
     This function builds the tcl script for the splash screen.
     """
@@ -196,6 +221,9 @@ def build_script(text_options=None):
         script.append(splash_canvas_text % text_options)
 
     script.append(transparent_setup)
-    script.append(align_windows)
+
+    script.append(pack_widgets)
+    script.append(position_window_on_top if always_on_top else position_window)
+    script.append(raise_window)
 
     return '\n'.join(script)
diff --git a/PyInstaller/building/templates.py b/PyInstaller/building/templates.py
--- a/PyInstaller/building/templates.py
+++ b/PyInstaller/building/templates.py
@@ -137,5 +137,6 @@
     text_pos=None,
     text_size=12,
     minify_script=True,
+    always_on_top=True,
 )
 """


Test patch: