diff --git a/CHANGELOG.md b/CHANGELOG.md index 8110b40a..e7beddb2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 (unreleased)= ## [Unreleased](https://github.com/jeertmans/manim-slides/compare/v5.1.10...HEAD) +(unreleased-changed)= +### Changed + +- The info window is now only shown in presentations when there + are multiple monitors. However, the `--show-info-window` option + was added to `manim-slides present` to force the info window. + When there are multiple monitors, the info window will no longer + be on the same monitor as the main window, unless overridden. + [@PeculiarProgrammer](https://github.com/PeculiarProgrammer) + [#482](https://github.com/jeertmans/manim-slides/pull/482) + (v5.1.10)= ## [v5.1.10](https://github.com/jeertmans/manim-slides/compare/v5.1.9...v5.1.10) diff --git a/manim_slides/present/__init__.py b/manim_slides/present/__init__.py index 94e071e9..ac82f31a 100644 --- a/manim_slides/present/__init__.py +++ b/manim_slides/present/__init__.py @@ -1,7 +1,7 @@ import signal import sys from pathlib import Path -from typing import Optional +from typing import Literal, Optional import click from click import Context, Parameter @@ -222,8 +222,14 @@ def str_to_int_or_none(value: str) -> Optional[int]: ) @click.option( "--hide-info-window", - is_flag=True, - help="Hide info window.", + flag_value="always", + help="Hide info window. By default, hide the info window if there is only one screen.", +) +@click.option( + "--show-info-window", + "hide_info_window", + flag_value="never", + help="Force to show info window.", ) @click.option( "--info-window-screen", @@ -231,11 +237,13 @@ def str_to_int_or_none(value: str) -> Optional[int]: metavar="NUMBER", type=int, default=None, - help="Put info window on the given screen (a.k.a. display).", + help="Put info window on the given screen (a.k.a. display). " + "If there is more than one screen, it will by default put the info window " + "on a different screen than the main player.", ) @click.help_option("-h", "--help") @verbosity_option -def present( +def present( # noqa: C901 scenes: list[str], config_path: Path, folder: Path, @@ -251,7 +259,7 @@ def present( screen_number: Optional[int], playback_rate: float, next_terminates_loop: bool, - hide_info_window: bool, + hide_info_window: Optional[Literal["always", "never"]], info_window_screen_number: Optional[int], ) -> None: """ @@ -294,22 +302,36 @@ def present( app = qapp() app.setApplicationName("Manim Slides") + screens = app.screens() + def get_screen(number: int) -> Optional[QScreen]: try: - return app.screens()[number] + return screens[number] except IndexError: logger.error( f"Invalid screen number {number}, " - f"allowed values are from 0 to {len(app.screens())-1} (incl.)" + f"allowed values are from 0 to {len(screens)-1} (incl.)" ) return None + should_hide_info_window = False + + if hide_info_window is None: + should_hide_info_window = len(screens) == 1 + elif hide_info_window == "always": + should_hide_info_window = True + + if should_hide_info_window and info_window_screen_number is not None: + logger.warning( + f"Ignoring `--info-window-screen` because `--hide-info-window` is set to `{hide_info_window}`." + ) + if screen_number is not None: screen = get_screen(screen_number) else: screen = None - if info_window_screen_number is not None: + if info_window_screen_number is not None and not should_hide_info_window: info_window_screen = get_screen(info_window_screen_number) else: info_window_screen = None @@ -333,11 +355,11 @@ def get_screen(number: int) -> Optional[QScreen]: screen=screen, playback_rate=playback_rate, next_terminates_loop=next_terminates_loop, - hide_info_window=hide_info_window, + hide_info_window=should_hide_info_window, info_window_screen=info_window_screen, ) - player.show() + player.show(screens) signal.signal(signal.SIGINT, signal.SIG_DFL) sys.exit(app.exec()) diff --git a/manim_slides/present/player.py b/manim_slides/present/player.py index f029a846..bd9ff473 100644 --- a/manim_slides/present/player.py +++ b/manim_slides/present/player.py @@ -28,7 +28,6 @@ class Info(QWidget): # type: ignore[misc] def __init__( self, *, - full_screen: bool, aspect_ratio_mode: Qt.AspectRatioMode, screen: Optional[QScreen], ) -> None: @@ -38,9 +37,6 @@ def __init__( self.setScreen(screen) self.move(screen.geometry().topLeft()) - if full_screen: - self.setWindowState(Qt.WindowFullScreen) - layout = QHBoxLayout() # Current slide view @@ -243,7 +239,6 @@ def __init__( self.slide_changed.connect(self.slide_changed_callback) self.info = Info( - full_screen=full_screen, aspect_ratio_mode=aspect_ratio_mode, screen=info_window_screen, ) @@ -484,11 +479,28 @@ def preview_next_slide(self) -> None: self.info.next_media_player.setSource(url) self.info.next_media_player.play() - def show(self) -> None: + def show(self, screens: list[QScreen]) -> None: + """Screens is necessary to prevent the info window from being shown on the same screen as the main window (especially in full screen mode).""" super().show() if not self.hide_info_window: - self.info.show() + if len(screens) > 1 and self.isFullScreen(): + self.ensure_different_screens(screens) + + if self.isFullScreen(): + self.info.showFullScreen() + else: + self.info.show() + + if ( + len(screens) > 1 and self.info.screen() == self.screen() + ): # It is better when Qt assigns the location, but if it fails to, this is a fallback + self.ensure_different_screens(screens) + + def ensure_different_screens(self, screens: list[QScreen]) -> None: + target_screen = screens[1] if self.screen() == screens[0] else screens[0] + self.info.setScreen(target_screen) + self.info.move(target_screen.geometry().topLeft()) @Slot() def close(self) -> None: @@ -538,8 +550,10 @@ def play_pause(self) -> None: def full_screen(self) -> None: if self.windowState() == Qt.WindowFullScreen: self.setWindowState(Qt.WindowNoState) + self.info.setWindowState(Qt.WindowNoState) else: self.setWindowState(Qt.WindowFullScreen) + self.info.setWindowState(Qt.WindowFullScreen) @Slot() def hide_mouse(self) -> None: diff --git a/uv.lock b/uv.lock index a82205aa..f73b5c56 100644 --- a/uv.lock +++ b/uv.lock @@ -1237,7 +1237,7 @@ wheels = [ [[package]] name = "manim-slides" -version = "5.1.9" +version = "5.1.10" source = { editable = "." } dependencies = [ { name = "av" }, @@ -1433,6 +1433,8 @@ dependencies = [ ] wheels = [ { url = "https://files.pythonhosted.org/packages/31/c9/ef3fbd0ee64bc64f2fcc6699e7ebbeb81c86f60abf79a624bab5039a047f/manimgl-1.6.1-py310-none-any.whl", hash = "sha256:8f1cd581b1656bf8b091b88909c96f3579b1a273e55b2ae9d55519bd4f2fe84c", size = 235947 }, + { url = "https://files.pythonhosted.org/packages/f2/5c/a29270cd293c85682d4e748cb939d8714bcdfe1ab95865317f8abfe9b522/manimgl-1.6.1-py37-none-any.whl", hash = "sha256:4d152b7191d922a78efb3b421a7db33b354ee54aecfe8806f86ec7b656b9c2d3", size = 235947 }, + { url = "https://files.pythonhosted.org/packages/00/2b/178c745905e99eef035698f1b794fcf631b2dd786dc123ecf180311b8017/manimgl-1.6.1-py38-none-any.whl", hash = "sha256:78f1a069ea97810c8bccd2e415e40b9c5d03ee7d485b0c5c16674ff786cd3a9b", size = 235944 }, { url = "https://files.pythonhosted.org/packages/1c/2c/b427f44673d2206cd19bfa58d8a53a35940bae5f115c71e68315fc8403bf/manimgl-1.6.1-py39-none-any.whl", hash = "sha256:b53deef6bb015859c397b0c7fc918005169969468aee81307636457eeea0435c", size = 235946 }, ] @@ -2175,8 +2177,6 @@ version = "6.0.0" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/18/c7/8c6872f7372eb6a6b2e4708b88419fb46b857f7a2e1892966b851cc79fc9/psutil-6.0.0.tar.gz", hash = "sha256:8faae4f310b6d969fa26ca0545338b21f73c6b15db7c4a8d934a5482faa818f2", size = 508067 } wheels = [ - { url = "https://files.pythonhosted.org/packages/c5/66/78c9c3020f573c58101dc43a44f6855d01bbbd747e24da2f0c4491200ea3/psutil-6.0.0-cp27-none-win32.whl", hash = "sha256:02b69001f44cc73c1c5279d02b30a817e339ceb258ad75997325e0e6169d8b35", size = 249766 }, - { url = "https://files.pythonhosted.org/packages/e1/3f/2403aa9558bea4d3854b0e5e567bc3dd8e9fbc1fc4453c0aa9aafeb75467/psutil-6.0.0-cp27-none-win_amd64.whl", hash = "sha256:21f1fb635deccd510f69f485b87433460a603919b45e2a324ad65b0cc74f8fb1", size = 253024 }, { url = "https://files.pythonhosted.org/packages/0b/37/f8da2fbd29690b3557cca414c1949f92162981920699cd62095a984983bf/psutil-6.0.0-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:c588a7e9b1173b6e866756dde596fd4cad94f9399daf99ad8c3258b3cb2b47a0", size = 250961 }, { url = "https://files.pythonhosted.org/packages/35/56/72f86175e81c656a01c4401cd3b1c923f891b31fbcebe98985894176d7c9/psutil-6.0.0-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ed2440ada7ef7d0d608f20ad89a04ec47d2d3ab7190896cd62ca5fc4fe08bf0", size = 287478 }, { url = "https://files.pythonhosted.org/packages/19/74/f59e7e0d392bc1070e9a70e2f9190d652487ac115bb16e2eff6b22ad1d24/psutil-6.0.0-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5fd9a97c8e94059b0ef54a7d4baf13b405011176c3b6ff257c247cae0d560ecd", size = 290455 },