1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246
|
"""Window routines to manage on-screen windows."""
from ctypes import c_int, byref
from .compat import stringify, utf8
from .common import SDLError
from .. import video
__all__ = ["Window"]
class Window(object):
"""Creates a visible window with an optional border and title text.
In SDL2, a window is the object through which visuals are displayed and
all input events are captured. This class is a Pythonic alternative to
working directly with SDL2's :obj:`~sdl2.SDL_Window` type, wrapping a
number of useful functions for working with windows.
The created Window is hidden by default, but can be shown using the
:meth:`~Window.show` method. Additionally, the type and properties of the
created window can be configured using various flags:
================================== =========================================
Flag Description
================================== =========================================
sdl2.SDL_WINDOW_SHOWN Will be shown when created
sdl2.SDL_WINDOW_HIDDEN Will be hidden when created
sdl2.SDL_WINDOW_BORDERLESS Will not be decorated by the OS
sdl2.SDL_WINDOW_RESIZABLE Will be resizable
sdl2.SDL_WINDOW_MINIMIZED Will be created in a minimized state
sdl2.SDL_WINDOW_MAXIMIZED Will be created in a maximized state
sdl2.SDL_WINDOW_FULLSCREEN Will be fullscreen
sdl2.SDL_WINDOW_FULLSCREEN_DESKTOP Will be fullscreen at the current desktop
resolution
sdl2.SDL_WINDOW_OPENGL Will be usable with an OpenGL context
sdl2.SDL_WINDOW_VULKAN Will be usable with a Vulkan instance
sdl2.SDL_WINDOW_METAL Will be usable with a Metal context
sdl2.SDL_WINDOW_ALLOW_HIGHDPI Will be created in high-DPI mode
(if supported)
sdl2.SDL_WINDOW_INPUT_FOCUS Will have input focus when created
sdl2.SDL_WINDOW_MOUSE_FOCUS Will have mouse focus when created
sdl2.SDL_WINDOW_INPUT_GRABBED Will prevent the mouse from leaving the
bounds of the window
sdl2.SDL_WINDOW_MOUSE_CAPTURE Will capture mouse to track input outside
of the window when created
================================== =========================================
There are also a few additional window creation flags that only affect the
X11 window manager (i.e. most distributions of Linux and BSD):
================================== =====================================
Flag Description
================================== =====================================
sdl2.SDL_WINDOW_ALWAYS_ON_TOP Should stay on top of other windows
sdl2.SDL_WINDOW_SKIP_TASKBAR Should not be added to the taskbar
sdl2.SDL_WINDOW_UTILITY Should be treated as a utility window
sdl2.SDL_WINDOW_TOOLTIP Should be treated as a tooltip
sdl2.SDL_WINDOW_POPUP_MENU Should be treated as a popup menu
================================== =====================================
To combine multiple flags, you can use a bitwise OR to combine two or more
together before passing them to the `flags` argument. For example, to create
a fullscreen window that supports an OpenGL context and is shown on
creation, you would use::
win_flags = (
sdl2.SDL_WINDOW_FULLSCREEN | sdl2.SDL_WINDOW_OPENGL |
sdl2.SDL_WINDOW_SHOWN
)
sdl2.ext.Window("PySDL2", (800, 600), flags=win_flags)
Args:
title (str): The title to use for the window.
size (tuple): The initial size (in pixels) of the window, in the format
`(width, height)`.
position (tuple, optional): The initial `(x, y)` coordinates of the
top-left corner of the window. If not specified, defaults to letting
the system's window manager choose a location for the window.
flags (int, optional): The window attribute flags with which the window
will be created. Defaults to `SDL_WINDOW_HIDDEN`.
Attributes:
window (:obj:`~sdl2.SDL_Window`, None): The underlying SDL2 Window
object. If the window has been closed, this value will be `None`.
"""
DEFAULTFLAGS = video.SDL_WINDOW_HIDDEN
DEFAULTPOS = (video.SDL_WINDOWPOS_UNDEFINED,
video.SDL_WINDOWPOS_UNDEFINED)
def __init__(self, title, size, position=None, flags=None):
if position is None:
position = self.DEFAULTPOS
if flags is None:
flags = self.DEFAULTFLAGS
self._title = title
self._position = position
self._flags = flags
self._size = size
self.window = None
self.create()
def __del__(self):
"""Releases the resources of the Window, implicitly destroying the
underlying SDL2 window."""
self.close()
@property
def position(self):
"""tuple: The (x, y) pixel coordinates of the top-left corner of the
window.
"""
x, y = c_int(), c_int()
video.SDL_GetWindowPosition(self.window, byref(x), byref(y))
return x.value, y.value
@position.setter
def position(self, value):
if not self.window:
raise SDLError("The window is not available")
video.SDL_SetWindowPosition(self.window, value[0], value[1])
self._position = value[0], value[1]
@property
def title(self):
"""str: The title of the window."""
return stringify(video.SDL_GetWindowTitle(self.window), "utf-8")
@title.setter
def title(self, value):
title_bytes = utf8(value).encode('utf-8')
video.SDL_SetWindowTitle(self.window, title_bytes)
self._title = value
@property
def size(self):
"""tuple: The dimensions of the window (in pixels) in the form
(width, height).
"""
w, h = c_int(), c_int()
video.SDL_GetWindowSize(self.window, byref(w), byref(h))
return w.value, h.value
@size.setter
def size(self, value):
video.SDL_SetWindowSize(self.window, value[0], value[1])
self._size = value[0], value[1]
def create(self):
"""Creates the window if it does not already exist."""
if self.window != None:
return
window = video.SDL_CreateWindow(utf8(self._title).encode('utf-8'),
self._position[0], self._position[1],
self._size[0], self._size[1],
self._flags)
if not window:
raise SDLError()
self.window = window.contents
def open(self):
"""Creates and shows the window."""
if self.window is None:
self.create()
self.show()
def close(self):
"""Closes and destroys the window.
Once this method has been called, the window cannot be re-opened.
However, you can create a new window with the same settings using the
:meth:`create` method.
"""
if hasattr(self, "window") and self.window != None:
video.SDL_DestroyWindow(self.window)
self.window = None
def show(self):
"""Shows the window on the display.
If the window is already visible, this method does nothing.
"""
video.SDL_ShowWindow(self.window)
def hide(self):
"""Hides the window.
If the window is already hidden, this method does nothing.
"""
video.SDL_HideWindow(self.window)
def maximize(self):
"""Maximizes the window."""
video.SDL_MaximizeWindow(self.window)
def minimize(self):
"""Minimizes the window into the system's dock or task bar."""
video.SDL_MinimizeWindow(self.window)
def restore(self):
"""Restores a minimized or maximized window to its original state.
If the window has not been minimized or maximized, this method does
nothing.
"""
video.SDL_RestoreWindow(self.window)
def refresh(self):
"""Updates the window to reflect any changes made to its surface.
.. note: This only needs to be called if the window surface was
acquired and modified using :meth:`get_surface`.
"""
video.SDL_UpdateWindowSurface(self.window)
def get_surface(self):
"""Gets the :obj:`~sdl2.SDL_Surface` used by the window.
This method obtains the SDL surface used by the window, which can be
then be modified to change the contents of the window (e.g draw shapes
or images) using functions such as :func:`sdl2.SDL_BlitSurface` or
:func:`sdl2.ext.fill`.
The obtained surface will be invalidated if the window is resized. As
such, you will need to call this method again whenever this happens
in order to continue to access the window's contents.
.. note: If using OpenGL/Vulkan/Metal rendering or the SDL rendering
API (e.g. :func:`sdl2.SDL_CreateRenderer`) for drawing to the
window, this method should not be used.
Returns:
:obj:`~sdl2.SDL_Surface`: The surface associated with the window.
"""
sf = video.SDL_GetWindowSurface(self.window)
if not sf:
raise SDLError()
return sf.contents
|