Skip to content

Commit 6c71960

Browse files
LibWebView: Add common source loop source for deferred_invoke() on macOS
Previously, `EventLoopImplementationMacOS` didn't process `deferred_invoke()` callbacks during window resizing because they were scheduled in the "default" run-loop mode, which isn't serviced while the run loop is in "Event Tracking" mode. Commit 3bbe1b0 changed socket notifiers to schedule in `kCFRunLoopCommonModes`, which kept IPC reads responsive during resizing (we process IPC messages in the notifier's read hook). This change does the same for `deferred_invoke()`: it installs a `CFRunLoopSource` in `kCFRunLoopCommonModes` and signals it whenever a deferred callback is enqueued.
1 parent d4deafe commit 6c71960

File tree

2 files changed

+45
-4
lines changed

2 files changed

+45
-4
lines changed

Libraries/LibWebView/EventLoop/EventLoopImplementationMacOS.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,13 @@ class WEBVIEW_API EventLoopImplementationMacOS final : public Core::EventLoopImp
4343
virtual bool was_exit_requested() const override;
4444
virtual void post_event(Core::EventReceiver& receiver, NonnullOwnPtr<Core::Event>&&) override;
4545

46+
virtual ~EventLoopImplementationMacOS() override;
47+
4648
private:
47-
EventLoopImplementationMacOS() = default;
49+
EventLoopImplementationMacOS();
50+
51+
struct Impl;
52+
NonnullOwnPtr<Impl> m_impl;
4853

4954
int m_exit_code { 0 };
5055
};

Libraries/LibWebView/EventLoop/EventLoopImplementationMacOS.mm

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,40 @@ static void post_application_event()
202202
[NSApp postEvent:event atStart:NO];
203203
}
204204

205+
struct EventLoopImplementationMacOS::Impl {
206+
Impl(EventLoopImplementationMacOS& event_loop_implementation)
207+
: run_loop(CFRunLoopGetCurrent())
208+
{
209+
CFRunLoopSourceContext context {};
210+
context.info = &event_loop_implementation;
211+
context.perform = [](void* info) {
212+
auto& self = *static_cast<EventLoopImplementationMacOS*>(info);
213+
self.m_impl->deferred_source_pending = false;
214+
self.m_thread_event_queue.process();
215+
};
216+
217+
deferred_source = CFRunLoopSourceCreate(kCFAllocatorDefault, 0, &context);
218+
CFRunLoopAddSource(run_loop, deferred_source, kCFRunLoopCommonModes);
219+
}
220+
221+
~Impl()
222+
{
223+
CFRunLoopRemoveSource(run_loop, deferred_source, kCFRunLoopCommonModes);
224+
CFRelease(deferred_source);
225+
}
226+
227+
CFRunLoopRef run_loop { nullptr };
228+
CFRunLoopSourceRef deferred_source { nullptr };
229+
Atomic<bool> deferred_source_pending { false };
230+
};
231+
232+
EventLoopImplementationMacOS::EventLoopImplementationMacOS()
233+
: m_impl(make<Impl>(*this))
234+
{
235+
}
236+
237+
EventLoopImplementationMacOS::~EventLoopImplementationMacOS() = default;
238+
205239
NonnullOwnPtr<Core::EventLoopImplementation> EventLoopManagerMacOS::make_implementation()
206240
{
207241
return EventLoopImplementationMacOS::create();
@@ -306,7 +340,7 @@ static void socket_notifier(CFSocketRef socket, CFSocketCallBackType notificatio
306340

307341
void EventLoopManagerMacOS::did_post_event()
308342
{
309-
post_application_event();
343+
CFRunLoopWakeUp(CFRunLoopGetCurrent());
310344
}
311345

312346
static void handle_signal(CFFileDescriptorRef f, CFOptionFlags callback_types, void* info)
@@ -407,8 +441,10 @@ static void handle_signal(CFFileDescriptorRef f, CFOptionFlags callback_types, v
407441
{
408442
m_thread_event_queue.post_event(receiver, move(event));
409443

410-
if (&m_thread_event_queue != &Core::ThreadEventQueue::current())
411-
wake();
444+
bool expected = false;
445+
if (m_impl->deferred_source && m_impl->deferred_source_pending.compare_exchange_strong(expected, true)) {
446+
CFRunLoopSourceSignal(m_impl->deferred_source);
447+
}
412448
}
413449

414450
}

0 commit comments

Comments
 (0)