Skip to content

Commit 3b33302

Browse files
committed
Update WindowEvent to handle all window event types
Try to reduce code duplication in general at the cost of several minor API breaks
1 parent 3e07cbf commit 3b33302

File tree

3 files changed

+118
-60
lines changed

3 files changed

+118
-60
lines changed

.vscode/settings.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,7 @@
206206
"htmlzip",
207207
"IBEAM",
208208
"ibus",
209+
"ICCPROF",
209210
"ifdef",
210211
"ifndef",
211212
"iinfo",

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ This project adheres to [Semantic Versioning](https://semver.org/) since version
1414
- `ClipboardUpdate` event.
1515
- `Drop` event.
1616
- `KeyboardEvent.pressed`, `KeyboardEvent.which`, `KeyboardEvent.window_id` attributes.
17+
- `WindowEvent.data` and `WindowEvent.window_id` attributes and added missing SDL3 window events.
1718

1819
### Changed
1920

tcod/event.py

Lines changed: 116 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -669,65 +669,113 @@ def _from_sdl_event(cls, sdl_event: _C_SDL_Event) -> Self:
669669
return cls(text=str(ffi.string(sdl_event.text.text, 32), encoding="utf8"), **_unpack_sdl_event(sdl_event))
670670

671671

672+
_WindowTypes = Literal[
673+
"WindowShown",
674+
"WindowHidden",
675+
"WindowExposed",
676+
"WindowMoved",
677+
"WindowResized",
678+
"PixelSizeChanged",
679+
"MetalViewResized",
680+
"WindowMinimized",
681+
"WindowMaximized",
682+
"WindowRestored",
683+
"WindowEnter",
684+
"WindowLeave",
685+
"WindowFocusGained",
686+
"WindowFocusLost",
687+
"WindowClose",
688+
"WindowTakeFocus",
689+
"WindowHitTest",
690+
"ICCProfileChanged",
691+
"DisplayChanged",
692+
"DisplayScaleChanged",
693+
"SafeAreaChanged",
694+
"Occluded",
695+
"EnterFullscreen",
696+
"LeaveFullscreen",
697+
"Destroyed",
698+
"HDRStateChanged",
699+
]
700+
701+
672702
@attrs.define(slots=True, kw_only=True)
673703
class WindowEvent(Event):
674-
"""A window event."""
675-
676-
type: Final[ # Narrowing final type.
677-
Literal[
678-
"WindowShown",
679-
"WindowHidden",
680-
"WindowExposed",
681-
"WindowMoved",
682-
"WindowResized",
683-
"WindowMinimized",
684-
"WindowMaximized",
685-
"WindowRestored",
686-
"WindowEnter",
687-
"WindowLeave",
688-
"WindowFocusGained",
689-
"WindowFocusLost",
690-
"WindowClose",
691-
"WindowTakeFocus",
692-
"WindowHitTest",
693-
]
694-
]
704+
"""A window event.
705+
706+
Example::
707+
708+
match event:
709+
case tcod.event.WindowEvent(type="WindowShown", window_id=window_id):
710+
print(f"Window {window_id} was shown")
711+
case tcod.event.WindowEvent(type="WindowHidden", window_id=window_id):
712+
print(f"Window {window_id} was hidden")
713+
case tcod.event.WindowEvent(type="WindowExposed", window_id=window_id):
714+
print(f"Window {window_id} was exposed and needs to be redrawn")
715+
case tcod.event.WindowEvent(type="WindowMoved", data=(x, y), window_id=window_id):
716+
print(f"Window {window_id} was moved to {x=},{y=}")
717+
case tcod.event.WindowEvent(type="WindowResized", data=(width, height), window_id=window_id):
718+
print(f"Window {window_id} was resized to {width=},{height=}")
719+
case tcod.event.WindowEvent(type="WindowMinimized", window_id=window_id):
720+
print(f"Window {window_id} was minimized")
721+
case tcod.event.WindowEvent(type="WindowMaximized", window_id=window_id):
722+
print(f"Window {window_id} was maximized")
723+
case tcod.event.WindowEvent(type="WindowRestored", window_id=window_id):
724+
print(f"Window {window_id} was restored")
725+
case tcod.event.WindowEvent(type="WindowEnter", window_id=window_id):
726+
print(f"Mouse cursor has entered window {window_id}")
727+
case tcod.event.WindowEvent(type="WindowLeave", window_id=window_id):
728+
print(f"Mouse cursor has left window {window_id}")
729+
case tcod.event.WindowEvent(type="WindowFocusGained", window_id=window_id):
730+
print(f"Window {window_id} has gained keyboard focus")
731+
case tcod.event.WindowEvent(type="WindowFocusLost", window_id=window_id):
732+
print(f"Window {window_id} has lost keyboard focus")
733+
case tcod.event.WindowEvent(type="WindowClose", window_id=window_id):
734+
print(f"Window {window_id} has been closed")
735+
case tcod.event.WindowEvent(type="DisplayChanged", data=(display_id, _), window_id=window_id):
736+
print(f"Window {window_id} has been moved to display {display_id}")
737+
case tcod.event.WindowEvent(type=subtype, data=data, window_id=window_id):
738+
print(f"Other window event {subtype} on window {window_id} with {data=}")
739+
740+
.. versionchanged:: Unreleased
741+
Added `data` and `window_id` attributes and added missing SDL3 window events.
742+
"""
743+
744+
type: Final[_WindowTypes]
695745
"""The current window event. This can be one of various options."""
696746

747+
window_id: int
748+
"""The SDL window ID associated with this event."""
749+
750+
data: tuple[int, int]
751+
"""The SDL data associated with this event. What these values are for depends on the event sub-type."""
752+
697753
@classmethod
698754
def _from_sdl_event(cls, sdl_event: _C_SDL_Event) -> WindowEvent | Undefined:
699755
if sdl_event.type not in _WINDOW_TYPES_FROM_ENUM:
700756
return Undefined._from_sdl_event(sdl_event)
701757
event_type: Final = _WINDOW_TYPES_FROM_ENUM[sdl_event.type]
702-
self: WindowEvent
758+
new_cls = cls
703759
if sdl_event.type == lib.SDL_EVENT_WINDOW_MOVED:
704-
self = WindowMoved(
705-
x=int(sdl_event.window.data1), y=int(sdl_event.window.data2), **_unpack_sdl_event(sdl_event)
706-
)
707-
elif sdl_event.type in (
708-
lib.SDL_EVENT_WINDOW_RESIZED,
709-
lib.SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED,
710-
):
711-
self = WindowResized(
712-
type=event_type, # type: ignore[arg-type] # Currently NOT validated
713-
width=int(sdl_event.window.data1),
714-
height=int(sdl_event.window.data2),
715-
**_unpack_sdl_event(sdl_event),
716-
)
717-
else:
718-
self = cls(
719-
type=event_type, # type: ignore[arg-type] # Currently NOT validated
720-
**_unpack_sdl_event(sdl_event),
721-
)
722-
return self
760+
new_cls = WindowMoved
761+
elif sdl_event.type == lib.SDL_EVENT_WINDOW_RESIZED:
762+
new_cls = WindowResized
763+
return new_cls(
764+
type=event_type,
765+
window_id=int(sdl_event.window.windowID),
766+
data=(int(sdl_event.window.data1), int(sdl_event.window.data2)),
767+
**_unpack_sdl_event(sdl_event),
768+
)
723769

724770

725-
_WINDOW_TYPES_FROM_ENUM: Final = {
771+
_WINDOW_TYPES_FROM_ENUM: Final[dict[int, _WindowTypes]] = {
726772
lib.SDL_EVENT_WINDOW_SHOWN: "WindowShown",
727773
lib.SDL_EVENT_WINDOW_HIDDEN: "WindowHidden",
728774
lib.SDL_EVENT_WINDOW_EXPOSED: "WindowExposed",
729775
lib.SDL_EVENT_WINDOW_MOVED: "WindowMoved",
730776
lib.SDL_EVENT_WINDOW_RESIZED: "WindowResized",
777+
lib.SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED: "PixelSizeChanged",
778+
lib.SDL_EVENT_WINDOW_METAL_VIEW_RESIZED: "MetalViewResized",
731779
lib.SDL_EVENT_WINDOW_MINIMIZED: "WindowMinimized",
732780
lib.SDL_EVENT_WINDOW_MAXIMIZED: "WindowMaximized",
733781
lib.SDL_EVENT_WINDOW_RESTORED: "WindowRestored",
@@ -737,42 +785,50 @@ def _from_sdl_event(cls, sdl_event: _C_SDL_Event) -> WindowEvent | Undefined:
737785
lib.SDL_EVENT_WINDOW_FOCUS_LOST: "WindowFocusLost",
738786
lib.SDL_EVENT_WINDOW_CLOSE_REQUESTED: "WindowClose",
739787
lib.SDL_EVENT_WINDOW_HIT_TEST: "WindowHitTest",
788+
lib.SDL_EVENT_WINDOW_ICCPROF_CHANGED: "ICCProfileChanged",
789+
lib.SDL_EVENT_WINDOW_DISPLAY_CHANGED: "DisplayChanged",
790+
lib.SDL_EVENT_WINDOW_DISPLAY_SCALE_CHANGED: "DisplayScaleChanged",
791+
lib.SDL_EVENT_WINDOW_SAFE_AREA_CHANGED: "SafeAreaChanged",
792+
lib.SDL_EVENT_WINDOW_OCCLUDED: "Occluded",
793+
lib.SDL_EVENT_WINDOW_ENTER_FULLSCREEN: "EnterFullscreen",
794+
lib.SDL_EVENT_WINDOW_LEAVE_FULLSCREEN: "LeaveFullscreen",
795+
lib.SDL_EVENT_WINDOW_DESTROYED: "Destroyed",
796+
lib.SDL_EVENT_WINDOW_HDR_STATE_CHANGED: "HDRStateChanged",
740797
}
741798

742799

743800
@attrs.define(slots=True, kw_only=True)
744801
class WindowMoved(WindowEvent):
745-
"""Window moved event.
802+
"""Window moved event."""
746803

747-
Attributes:
748-
x (int): Movement on the x-axis.
749-
y (int): Movement on the y-axis.
750-
"""
751-
752-
type: Final[Literal["WINDOWMOVED"]] = "WINDOWMOVED" # type: ignore[assignment,misc]
753-
"""Always "WINDOWMOVED"."""
804+
@property
805+
def x(self) -> int:
806+
"""Movement on the x-axis."""
807+
return self.data[0]
754808

755-
x: int
756-
y: int
809+
@property
810+
def y(self) -> int:
811+
"""Movement on the y-axis."""
812+
return self.data[1]
757813

758814

759815
@attrs.define(slots=True, kw_only=True)
760816
class WindowResized(WindowEvent):
761817
"""Window resized event.
762818
763-
Attributes:
764-
width (int): The current width of the window.
765-
height (int): The current height of the window.
766-
767819
.. versionchanged:: 19.4
768820
Removed "WindowSizeChanged" type.
769821
"""
770822

771-
type: Final[Literal["WindowResized"]] = "WindowResized" # type: ignore[misc]
772-
"""Always "WindowResized"."""
823+
@property
824+
def width(self) -> int:
825+
"""The current width of the window."""
826+
return self.data[0]
773827

774-
width: int
775-
height: int
828+
@property
829+
def height(self) -> int:
830+
"""The current height of the window."""
831+
return self.data[1]
776832

777833

778834
@attrs.define(slots=True, kw_only=True)

0 commit comments

Comments
 (0)