# ---------------------------------------------------------------------------- # pyglet # Copyright (c) 2006-2008 Alex Holkner # Copyright (c) 2008-2021 pyglet contributors # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # * Neither the name of pyglet nor the names of its # contributors may be used to endorse or promote products # derived from this software without specific prior written # permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # ---------------------------------------------------------------------------- from pyglet import gl from pyglet import app from pyglet import window from pyglet import canvas class Display: """A display device supporting one or more screens. .. versionadded:: 1.2 """ name = None """Name of this display, if applicable. :type: str """ x_screen = None """The X11 screen number of this display, if applicable. :type: int """ def __init__(self, name=None, x_screen=None): """Create a display connection for the given name and screen. On X11, :attr:`name` is of the form ``"hostname:display"``, where the default is usually ``":1"``. On X11, :attr:`x_screen` gives the X screen number to use with this display. A pyglet display can only be used with one X screen; open multiple display connections to access multiple X screens. Note that TwinView, Xinerama, xrandr and other extensions present multiple monitors on a single X screen; this is usually the preferred mechanism for working with multiple monitors under X11 and allows each screen to be accessed through a single pyglet`~pyglet.canvas.Display` On platforms other than X11, :attr:`name` and :attr:`x_screen` are ignored; there is only a single display device on these systems. :Parameters: name : str The name of the display to connect to. x_screen : int The X11 screen number to use. """ canvas._displays.add(self) def get_screens(self): """Get the available screens. A typical multi-monitor workstation comprises one :class:`Display` with multiple :class:`Screen` s. This method returns a list of screens which can be enumerated to select one for full-screen display. For the purposes of creating an OpenGL config, the default screen will suffice. :rtype: list of :class:`Screen` """ raise NotImplementedError('abstract') def get_default_screen(self): """Get the default screen as specified by the user's operating system preferences. :rtype: :class:`Screen` """ return self.get_screens()[0] def get_windows(self): """Get the windows currently attached to this display. :rtype: sequence of :class:`~pyglet.window.Window` """ return [window for window in app.windows if window.display is self] class Screen: """A virtual monitor that supports fullscreen windows. Screens typically map onto a physical display such as a monitor, television or projector. Selecting a screen for a window has no effect unless the window is made fullscreen, in which case the window will fill only that particular virtual screen. The :attr:`width` and :attr:`height` attributes of a screen give the current resolution of the screen. The :attr:`x` and :attr:`y` attributes give the global location of the top-left corner of the screen. This is useful for determining if screens are arranged above or next to one another. Use :func:`~Display.get_screens` or :func:`~Display.get_default_screen` to obtain an instance of this class. """ def __init__(self, display, x, y, width, height): """ :parameters: `display` : `~pyglet.canvas.Display` :attr:`display` `x` : int Left edge :attr:`x` `y` : int Top edge :attr:`y` `width` : int :attr:`width` `height` : int :attr:`height` """ self.display = display """Display this screen belongs to.""" self.x = x """Left edge of the screen on the virtual desktop.""" self.y = y """Top edge of the screen on the virtual desktop.""" self.width = width """Width of the screen, in pixels.""" self.height = height """Height of the screen, in pixels.""" def __repr__(self): return '{}(x={}, y={}, width={}, height={})'.format(self.__class__.__name__, self.x, self.y, self.width, self.height) def get_best_config(self, template=None): """Get the best available GL config. Any required attributes can be specified in `template`. If no configuration matches the template, :class:`~pyglet.window.NoSuchConfigException` will be raised. :deprecated: Use :meth:`pyglet.gl.Config.match`. :Parameters: `template` : `pyglet.gl.Config` A configuration with desired attributes filled in. :rtype: :class:`~pyglet.gl.Config` :return: A configuration supported by the platform that best fulfils the needs described by the template. """ configs = None if template is None: for template_config in [gl.Config(double_buffer=True, depth_size=24, major_version=3, minor_version=3), gl.Config(double_buffer=True, depth_size=16, major_version=3, minor_version=3), None]: try: configs = self.get_matching_configs(template_config) break except window.NoSuchConfigException: pass else: configs = self.get_matching_configs(template) if not configs: raise window.NoSuchConfigException() return configs[0] def get_matching_configs(self, template): """Get a list of configs that match a specification. Any attributes specified in `template` will have values equal to or greater in each returned config. If no configs satisfy the template, an empty list is returned. :deprecated: Use :meth:`pyglet.gl.Config.match`. :Parameters: `template` : `pyglet.gl.Config` A configuration with desired attributes filled in. :rtype: list of :class:`~pyglet.gl.Config` :return: A list of matching configs. """ raise NotImplementedError('abstract') def get_modes(self): """Get a list of screen modes supported by this screen. :rtype: list of :class:`ScreenMode` .. versionadded:: 1.2 """ raise NotImplementedError('abstract') def get_mode(self): """Get the current display mode for this screen. :rtype: :class:`ScreenMode` .. versionadded:: 1.2 """ raise NotImplementedError('abstract') def get_closest_mode(self, width, height): """Get the screen mode that best matches a given size. If no supported mode exactly equals the requested size, a larger one is returned; or ``None`` if no mode is large enough. :Parameters: `width` : int Requested screen width. `height` : int Requested screen height. :rtype: :class:`ScreenMode` .. versionadded:: 1.2 """ # Best mode is one with smallest resolution larger than width/height, # with depth and refresh rate equal to current mode. current = self.get_mode() best = None for mode in self.get_modes(): # Reject resolutions that are too small if mode.width < width or mode.height < height: continue if best is None: best = mode # Must strictly dominate dimensions if (mode.width <= best.width and mode.height <= best.height and (mode.width < best.width or mode.height < best.height)): best = mode # Preferably match rate, then depth. if mode.width == best.width and mode.height == best.height: points = 0 if mode.rate == current.rate: points += 2 if best.rate == current.rate: points -= 2 if mode.depth == current.depth: points += 1 if best.depth == current.depth: points -= 1 if points > 0: best = mode return best def set_mode(self, mode): """Set the display mode for this screen. The mode must be one previously returned by :meth:`get_mode` or :meth:`get_modes`. :Parameters: `mode` : `ScreenMode` Screen mode to switch this screen to. """ raise NotImplementedError('abstract') def restore_mode(self): """Restore the screen mode to the user's default. """ raise NotImplementedError('abstract') class ScreenMode: """Screen resolution and display settings. Applications should not construct `ScreenMode` instances themselves; see :meth:`Screen.get_modes`. The :attr:`depth` and :attr:`rate` variables may be ``None`` if the operating system does not provide relevant data. .. versionadded:: 1.2 """ width = None """Width of screen, in pixels. :type: int """ height = None """Height of screen, in pixels. :type: int """ depth = None """Pixel color depth, in bits per pixel. :type: int """ rate = None """Screen refresh rate in Hz. :type: int """ def __init__(self, screen): """ :parameters: `screen` : `Screen` """ self.screen = screen def __repr__(self): return '%s(width=%r, height=%r, depth=%r, rate=%r)' % ( self.__class__.__name__, self.width, self.height, self.depth, self.rate) class Canvas: """Abstract drawing area. Canvases are used internally by pyglet to represent drawing areas -- either within a window or full-screen. .. versionadded:: 1.2 """ def __init__(self, display): """ :parameters: `display` : `Display` :attr:`display` """ self.display = display """Display this canvas was created on."""