@@ -8,6 +8,7 @@ import Karm.Core;
88import Karm.Gfx;
99import Karm.Sys;
1010import Strata.Protos;
11+ import Karm.Logger;
1112
1213namespace Karm ::App::_Embed {
1314
@@ -19,6 +20,7 @@ struct SkiftWindow : Window {
1920 Rc<Strata::Protos::Surface> _surface;
2021 bool _dirty = false ;
2122 bool _closed = false ;
23+ Opt<Math::Vec2i> _shouldResize;
2224
2325 SkiftWindow (SkiftApplication& application, Strata::IShell::WindowId id, Rc<Strata::Protos::Surface> surface)
2426 : _application(application), _id(id), _surface(surface) {}
@@ -72,8 +74,6 @@ struct SkiftApplication : Application {
7274 }
7375
7476 Async::Task<Rc<Window>> createWindowAsync (WindowProps const & props, Async::CancellationToken ct) override {
75- // NOTE: The Window API is synchronous, but Strata is async.
76- // We use Sys::run to block until the window is created by the shell.
7777 auto [id, actual] = co_trya$(_endpoint->callAsync (
7878 _shell,
7979 Strata::IShell::WindowCreate{
@@ -102,23 +102,38 @@ struct SkiftApplication : Application {
102102 co_return Ok (window);
103103 }
104104
105- void pollMessage (Rc<Handler> handler) {
106- while (auto maybeMessage = _endpoint->tryRecv ()) {
107- if (maybeMessage->is <Strata::IShell::WindowEvent>()) {
108- auto m = maybeMessage->unpack <Strata::IShell::WindowEvent>().unwrap ();
109- auto windowId = WindowId{m.window };
110-
111- m.event .visit ([&](auto const & event) {
112- using T = Meta::RemoveConstVolatileRef<decltype (event)>;
113-
114- if constexpr (Meta::Contains<T, MouseEvent, KeyboardEvent, TypeEvent>) {
115- handler->handle <T>(windowId, event);
116- } else if constexpr (Meta::Same<T, RequestCloseEvent>) {
117- _exited = true ;
118- }
119- });
105+ Res<> _handleWindowEvent (Sys::Message& message, Rc<Handler> handler) {
106+ auto [windowId, payload] = try $(message.unpack <Strata::IShell::WindowEvent>());
107+ payload.visit ([&]<typename E>(E const & event) {
108+ using T = Meta::RemoveConstVolatileRef<E>;
109+
110+ if constexpr (Meta::Contains<T, MouseEvent, KeyboardEvent, TypeEvent>) {
111+ handler->handle <T>(App::WindowId{windowId}, event);
112+ } else if constexpr (Meta::Same<T, RequestCloseEvent>) {
113+ _exited = true ;
120114 }
115+ });
116+ return Ok ();
117+ }
118+
119+ Res<> _handleWindowUpdate (Sys::Message& message) {
120+ auto [windowId, props] = try $(message.unpack <Strata::IShell::WindowUpdate>());
121+ auto * window = try $(_windows.tryGet (windowId).okOr (Error::invalidInput (" no such window" )));
122+ // FIXME: We should probably have a separated hello message that pass stuff like color scheme and form factor
123+ App::formFactor = props.formFactor ;
124+ window->_shouldResize = props.size ;
125+ return Ok ();
126+ }
127+
128+ Res<> _pollMessages (Rc<Handler> handler) {
129+ while (auto maybeMessage = _endpoint->tryRecv ()) {
130+ auto & message = maybeMessage.unwrap ();
131+ if (message.is <Strata::IShell::WindowEvent>())
132+ try $(_handleWindowEvent (message, handler));
133+ else if (message.is <Strata::IShell::WindowUpdate>())
134+ try $(_handleWindowUpdate (message));
121135 }
136+ return Ok ();
122137 }
123138
124139 bool exited () {
@@ -128,15 +143,45 @@ struct SkiftApplication : Application {
128143 return true ;
129144 }
130145
146+ Async::Task<> _handleWindowResizeAsync (Rc<Handler> handler, Async::CancellationToken ct) {
147+ for (auto [id, window] : _windows.iterUnordered ()) {
148+ if (not window->_shouldResize )
149+ continue ;
150+
151+ auto size = window->_shouldResize .unwrap ();
152+ logDebug (" new size {}" , size);
153+
154+ auto newSurface = co_try$(Strata::Protos::Surface::create (size));
155+
156+ co_trya$(_endpoint->callAsync (
157+ _shell,
158+ Strata::IShell::WindowAttach{
159+ id,
160+ newSurface,
161+ },
162+ ct
163+ ));
164+
165+ window->_surface = newSurface;
166+ window->_shouldResize = NONE;
167+ handler->handle <ResizeEvent>(window->id (), size);
168+ }
169+
170+ co_return Ok ();
171+ }
172+
131173 Async::Task<> runAsync (Rc<Handler> handler, Async::CancellationToken ct) override {
132174 Duration const frameDuration = Duration::fromMSecs (16 );
133175 Instant nextFrameTime = Sys::instant ();
134176
135177 while (not exited ()) {
136178 nextFrameTime = nextFrameTime + frameDuration;
137179
138- pollMessage (handler);
180+ if (auto res = _pollMessages (handler); not res) {
181+ logError (" failed to pull message from server: {}" , res);
182+ }
139183
184+ co_trya$(_handleWindowResizeAsync (handler, ct));
140185 handler->update ();
141186
142187 for (auto [id, window] : _windows.iterUnordered ()) {
0 commit comments