diff --git a/moderngl_window/__init__.py b/moderngl_window/__init__.py index 55fcf44..e5d81e4 100644 --- a/moderngl_window/__init__.py +++ b/moderngl_window/__init__.py @@ -198,6 +198,7 @@ def run_window_config(config_cls: WindowConfig, timer=None, args=None) -> None: resizable=values.resizable if values.resizable is not None else config_cls.resizable, + visible=config_cls.visible, gl_version=config_cls.gl_version, aspect_ratio=config_cls.aspect_ratio, vsync=values.vsync if values.vsync is not None else config_cls.vsync, @@ -271,6 +272,13 @@ def create_parser(): default=None, help="Enable/disable window resize", ) + parser.add_argument( + "-hd", + "--hidden", + type=valid_bool, + default=False, + help="Start the window in hidden mode", + ) parser.add_argument( "-s", "--samples", diff --git a/moderngl_window/context/base/window.py b/moderngl_window/context/base/window.py index d5e84ec..b5e4e3c 100644 --- a/moderngl_window/context/base/window.py +++ b/moderngl_window/context/base/window.py @@ -82,6 +82,7 @@ def __init__( gl_version=(3, 3), size=(1280, 720), resizable=True, + visible=True, fullscreen=False, vsync=True, aspect_ratio: float = None, @@ -97,6 +98,7 @@ def __init__( gl_version (tuple): Major and minor version of the opengl context to create size (tuple): Window size x, y resizable (bool): Should the window be resizable? + visible (bool): Should the window be visible when created? fullscreen (bool): Open window in fullscreen mode vsync (bool): Enable/disable vsync aspect_ratio (float): The desired fixed aspect ratio. Can be set to ``None`` to make @@ -109,6 +111,7 @@ def __init__( self._gl_version = gl_version self._width, self._height = int(size[0]), int(size[1]) self._resizable = resizable + self._visible = visible self._buffer_width, self._buffer_height = size self._fullscreen = fullscreen self._vsync = vsync @@ -366,6 +369,32 @@ def resizable(self) -> bool: def resizable(self, value: bool) -> None: self._resizable = value + @property + def visible(self) -> bool: + """bool: Window is visible""" + return self._visible + + @visible.setter + def visible(self, value: bool) -> None: + self._visible = value + + @property + def hidden(self) -> bool: + """bool: Window is hidden""" + return not self._visible + + @hidden.setter + def hidden(self, value: bool) -> None: + self._visible = not value + + def hide(self) -> None: + """Hide the window""" + self.visible = False + + def show(self) -> None: + """Show the window""" + self.visible = True + @property def fullscreen(self) -> bool: """bool: Window is in fullscreen mode""" @@ -932,6 +961,15 @@ def key_event(self, key, action, modifiers): # Default value resizable = True """ + visible = True + """ + Determines if the window should be visible when created + + .. code:: python + + # Default value + visible = True + """ gl_version = (3, 3) """ The minimum required OpenGL version required diff --git a/moderngl_window/context/glfw/window.py b/moderngl_window/context/glfw/window.py index 4e4d013..63076c6 100644 --- a/moderngl_window/context/glfw/window.py +++ b/moderngl_window/context/glfw/window.py @@ -38,6 +38,7 @@ def __init__(self, **kwargs): glfw.window_hint(glfw.OPENGL_PROFILE, glfw.OPENGL_CORE_PROFILE) glfw.window_hint(glfw.OPENGL_FORWARD_COMPAT, True) glfw.window_hint(glfw.RESIZABLE, self.resizable) + glfw.window_hint(glfw.VISIBLE, self.visible) glfw.window_hint(glfw.DOUBLEBUFFER, True) glfw.window_hint(glfw.DEPTH_BITS, 24) glfw.window_hint(glfw.STENCIL_BITS, 8) @@ -158,6 +159,25 @@ def position(self) -> Tuple[int, int]: def position(self, value: Tuple[int, int]): self._position = glfw.set_window_pos(self._window, value[0], value[1]) + @property + def visible(self) -> bool: + """bool: Is the window visible? + + This property can also be set:: + + # Hide or show the window + window.visible = False + """ + return self._visible + + @visible.setter + def visible(self, value: bool): + self._visible = value + if value: + glfw.show_window(self._window) + else: + glfw.hide_window(self._window) + @property def cursor(self) -> bool: """bool: Should the mouse cursor be visible inside the window? diff --git a/moderngl_window/context/pygame2/window.py b/moderngl_window/context/pygame2/window.py index bd44242..430e61c 100644 --- a/moderngl_window/context/pygame2/window.py +++ b/moderngl_window/context/pygame2/window.py @@ -53,6 +53,9 @@ def __init__(self, **kwargs): if self.resizable: self._flags |= pygame.RESIZABLE + if not self._visible: + self._flags |= pygame.HIDDEN + self._set_mode() self.title = self._title self.cursor = self._cursor @@ -113,6 +116,25 @@ def position(self) -> Tuple[int, int]: def position(self, value: Tuple[int, int]): self._sdl_window.position = value + @property + def visible(self) -> bool: + """bool: Is the window visible? + + This property can also be set:: + + # Hide or show the window + window.visible = False + """ + return self._visible + + @visible.setter + def visible(self, value: bool): + self._visible = value + if value: + self._sdl_window.show() + else: + self._sdl_window.hide() + @property def cursor(self) -> bool: """bool: Should the mouse cursor be visible inside the window? diff --git a/moderngl_window/context/pyglet/window.py b/moderngl_window/context/pyglet/window.py index 74c9881..9de801f 100644 --- a/moderngl_window/context/pyglet/window.py +++ b/moderngl_window/context/pyglet/window.py @@ -58,6 +58,7 @@ def __init__(self, **kwargs): height=self._height, caption=self._title, resizable=self._resizable, + visible=self._visible, vsync=self._vsync, fullscreen=self._fullscreen, config=config, @@ -117,6 +118,22 @@ def position(self) -> Tuple[int, int]: def position(self, value: Tuple[int, int]): self._window.set_location(value[0], value[1]) + @property + def visible(self) -> bool: + """bool: Is the window visible? + + This property can also be set:: + + # Hide or show the window + window.visible = False + """ + return self._visible + + @visible.setter + def visible(self, value: bool): + self._visible = value + self._window.set_visible(value) + @property def cursor(self) -> bool: """bool: Should the mouse cursor be visible inside the window? diff --git a/moderngl_window/context/pyqt5/window.py b/moderngl_window/context/pyqt5/window.py index 5300e1b..2ac5277 100644 --- a/moderngl_window/context/pyqt5/window.py +++ b/moderngl_window/context/pyqt5/window.py @@ -72,11 +72,14 @@ def __init__(self, **kwargs): else: self._widget.setFixedSize(self.width, self.height) + if not self.visible: + self._widget.hide() + # Center the window on the screen if in window mode if not self.fullscreen: center_window_position = ( - self.position[0] - self.width / 2, - self.position[1] - self.height / 2, + int(self.position[0] - self.width / 2), + int(self.position[1] - self.height / 2), ) self._widget.move(*center_window_position) @@ -155,6 +158,25 @@ def position(self) -> Tuple[int, int]: def position(self, value: Tuple[int, int]): self._widget.setGeometry(value[0], value[1], self._width, self._height) + @property + def visible(self) -> bool: + """bool: Is the window visible? + + This property can also be set:: + + # Hide or show the window + window.visible = False + """ + return self._visible + + @visible.setter + def visible(self, value: bool): + self._visible = value + if value: + self._widget.show() + else: + self._widget.hide() + def swap_buffers(self) -> None: """Swap buffers, set viewport, trigger events and increment frame counter""" self._widget.swapBuffers() diff --git a/moderngl_window/context/pyside2/window.py b/moderngl_window/context/pyside2/window.py index 1d12f16..4aa5cf5 100644 --- a/moderngl_window/context/pyside2/window.py +++ b/moderngl_window/context/pyside2/window.py @@ -72,6 +72,9 @@ def __init__(self, **kwargs): else: self._widget.setFixedSize(self.width, self.height) + if not self.visible: + self._widget.hide() + # Center the window on the screen if in window mode if not self.fullscreen: center_window_position = ( @@ -139,6 +142,25 @@ def size(self, value: Tuple[int, int]): pos = self.position self._widget.setGeometry(pos[0], pos[1], value[0], value[1]) + @property + def visible(self) -> bool: + """bool: Is the window visible? + + This property can also be set:: + + # Hide or show the window + window.visible = False + """ + return self._visible + + @visible.setter + def visible(self, value: bool): + self._visible = value + if value: + self._widget.show() + else: + self._widget.hide() + @property def position(self) -> Tuple[int, int]: """Tuple[int, int]: The current window position. diff --git a/moderngl_window/context/sdl2/window.py b/moderngl_window/context/sdl2/window.py index 5c70a35..786e744 100644 --- a/moderngl_window/context/sdl2/window.py +++ b/moderngl_window/context/sdl2/window.py @@ -57,6 +57,9 @@ def __init__(self, **kwargs): if self.resizable: flags |= sdl2.SDL_WINDOW_RESIZABLE + if not self._visible: + flags |= sdl2.SDL_WINDOW_HIDDEN + self._window = sdl2.SDL_CreateWindow( self.title.encode(), sdl2.SDL_WINDOWPOS_UNDEFINED, @@ -125,6 +128,25 @@ def position(self) -> Tuple[int, int]: def position(self, value: Tuple[int, int]): sdl2.SDL_SetWindowPosition(self._window, value[0], value[1]) + @property + def visible(self) -> bool: + """bool: Is the window visible? + + This property can also be set:: + + # Hide or show the window + window.visible = False + """ + return self._visible + + @visible.setter + def visible(self, value: bool): + self._visible = value + if value: + sdl2.SDL_ShowWindow(self._window) + else: + sdl2.SDL_HideWindow(self._window) + @property def cursor(self) -> bool: """bool: Should the mouse cursor be visible inside the window? diff --git a/moderngl_window/context/tk/window.py b/moderngl_window/context/tk/window.py index 9e18fa9..f45547f 100644 --- a/moderngl_window/context/tk/window.py +++ b/moderngl_window/context/tk/window.py @@ -93,6 +93,25 @@ def position(self) -> Tuple[int, int]: def position(self, value: Tuple[int, int]): self._tk.geometry("+{}+{}".format(value[0], value[1])) + @property + def visible(self) -> bool: + """bool: Is the window visible? + + This property can also be set:: + + # Hide or show the window + window.visible = False + """ + return self._visible + + @visible.setter + def visible(self, value: bool): + self._visible = value + if value: + self._tk.deiconify() + else: + self._tk.withdraw() + @property def cursor(self) -> bool: """bool: Should the mouse cursor be visible inside the window?