载入中...
搜索中...
未找到
EventSink.cpp
浏览该文件的文档.
1// Keeps the window settings and the render surface aligned with the platform.
2//
3// Two things used to live in the SDL event pump and forced it to depend on both
4// window and graphics: resize handling, and the app background/foreground
5// callback that tears down and rebuilds the Vulkan surface on mobile.
6
7#include "common/Capability.h"
10#include "window/Window.h"
12#include "window/sdl/Window.h"
13
14#include <SDL2/SDL.h>
15#include <SDL2/SDL_vulkan.h>
16
17#include <algorithm>
18
20namespace {
21
22eve::window::Window *g_owner = nullptr;
23
25void syncWindowPixelSize() {
26 auto *win = g_owner;
27 if (!win) return;
28 auto *sdlWin = dynamic_cast<Window *>(win);
29 if (!sdlWin) return;
30 SDL_Window *native = static_cast<SDL_Window *>(sdlWin->getHandle());
31 if (!native) return;
32
33 int lw = 0, lh = 0, pw = 0, ph = 0;
34 SDL_GetWindowSize(native, &lw, &lh);
35 SDL_Vulkan_GetDrawableSize(native, &pw, &ph);
36 if (pw <= 0 || ph <= 0) {
37 pw = lw;
38 ph = lh;
39 }
40 WindowSettings s = win->getWindowSettings();
41 s.width = static_cast<uint16_t>(std::max(lw, 1));
42 s.height = static_cast<uint16_t>(std::max(lh, 1));
43 // Keep settings + graphics viewport aligned after rotation / resume.
44 sdlWin->updateSettings(s, true);
45}
46
53int SDLCALL watchAppEvents(void * /*udata*/, SDL_Event *event) {
54 auto *surfaceHost = eve::cap::query<IWindowSurfaceHost>();
55 if (!surfaceHost) return 1;
56
57 switch (event->type) {
58 case SDL_APP_DIDENTERBACKGROUND:
59 // Stop presenting: the native surface is being torn down.
60 surfaceHost->setActive(false);
61 break;
62 case SDL_APP_WILLENTERFOREGROUND:
63 case SDL_APP_DIDENTERFOREGROUND:
64 // The native window is recreated on resume; rebuild the render
65 // surface and swapchain, then resume presenting.
66 surfaceHost->requestSurfaceRecreate();
67 surfaceHost->setActive(true);
68 syncWindowPixelSize();
69 break;
70 default:
71 break;
72 }
73 return 1;
74}
75
76class WindowEventSink : public eve::platform_event::IPlatformEventSink {
77public:
78 bool shouldConsumePlatformEvent(const void *nativeEvent) override {
79 const auto &e = *static_cast<const SDL_Event *>(nativeEvent);
80 if (e.type == SDL_WINDOWEVENT && (e.window.event == SDL_WINDOWEVENT_SIZE_CHANGED ||
81 e.window.event == SDL_WINDOWEVENT_RESIZED))
82 syncWindowPixelSize();
83 // Never consume: SDL_WINDOWEVENT_CLOSE still has to reach the pump,
84 // which turns it into "quit".
85 return false;
86 }
87
88 void onPumpFinished() override {
89 // Deferred to the first pump because the watch can only be added once
90 // SDL is initialized, which is later than static registration.
91 if (watchInstalled_) return;
92 watchInstalled_ = true;
93 SDL_AddEventWatch(watchAppEvents, nullptr);
94 }
95
96private:
97 bool watchInstalled_ = false;
98};
99
100struct Register {
101 Register() {
102 static WindowEventSink sink;
103 eve::cap::addListener<eve::platform_event::IPlatformEventSink>(
105 }
106} g_register;
107
108} // namespace
109
110void bindWindowEventSinkOwner(eve::window::Window *owner) noexcept { g_owner = owner; }
111
112} // namespace eve::window::sdl
const std::string & s
EVENGINE_API_FOUNDATION public API.
Platform window interface (SDL implementation on desktop/mobile). Script: win <- eve....
Definition Window.h:47
void bindWindowEventSinkOwner(eve::window::Window *owner) noexcept
Bind the live Window module into the SDL event sink. @ownership Borrowed; cleared when the Window mod...
Display settings for window creation/resize. width/height == 0 selects the desktop display mode size.
Definition Window.h:18