mirror of
https://github.com/lightpanda-io/browser.git
synced 2025-10-29 23:23:28 +00:00
Merge pull request #766 from lightpanda-io/slow_down_animation_frame
Delay requestAnimation
This commit is contained in:
@@ -163,50 +163,33 @@ pub const Window = struct {
|
|||||||
return &self.performance;
|
return &self.performance;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tells the browser you wish to perform an animation. It requests the browser to call a user-supplied callback function before the next repaint.
|
pub fn _requestAnimationFrame(self: *Window, cbk: Function, page: *Page) !u32 {
|
||||||
// fn callback(timestamp: f64)
|
return self.createTimeout(cbk, 5, page, .{.animation_frame = true});
|
||||||
// Returns the request ID, that uniquely identifies the entry in the callback list.
|
|
||||||
pub fn _requestAnimationFrame(
|
|
||||||
self: *Window,
|
|
||||||
callback: Function,
|
|
||||||
) !u32 {
|
|
||||||
// We immediately execute the callback, but this may not be correct TBD.
|
|
||||||
// Since: When multiple callbacks queued by requestAnimationFrame() begin to fire in a single frame, each receives the same timestamp even though time has passed during the computation of every previous callback's workload.
|
|
||||||
var result: Function.Result = undefined;
|
|
||||||
callback.tryCall(void, .{self.performance._now()}, &result) catch {
|
|
||||||
log.debug(.user_script, "callback error", .{
|
|
||||||
.err = result.exception,
|
|
||||||
.stack = result.stack,
|
|
||||||
.source = "requestAnimationFrame",
|
|
||||||
});
|
|
||||||
};
|
|
||||||
return 99; // not unique, but user cannot make assumptions about it. cancelAnimationFrame will be too late anyway.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cancels an animation frame request previously scheduled through requestAnimationFrame().
|
pub fn _cancelAnimationFrame(self: *Window, id: u32, page: *Page) !void {
|
||||||
// This is a no-op since _requestAnimationFrame immediately executes the callback.
|
const kv = self.timers.fetchRemove(id) orelse return;
|
||||||
pub fn _cancelAnimationFrame(_: *Window, request_id: u32) void {
|
return page.loop.cancel(kv.value.loop_id);
|
||||||
_ = request_id;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO handle callback arguments.
|
// TODO handle callback arguments.
|
||||||
pub fn _setTimeout(self: *Window, cbk: Function, delay: ?u32, page: *Page) !u32 {
|
pub fn _setTimeout(self: *Window, cbk: Function, delay: ?u32, page: *Page) !u32 {
|
||||||
return self.createTimeout(cbk, delay, page, false);
|
return self.createTimeout(cbk, delay, page, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO handle callback arguments.
|
// TODO handle callback arguments.
|
||||||
pub fn _setInterval(self: *Window, cbk: Function, delay: ?u32, page: *Page) !u32 {
|
pub fn _setInterval(self: *Window, cbk: Function, delay: ?u32, page: *Page) !u32 {
|
||||||
return self.createTimeout(cbk, delay, page, true);
|
return self.createTimeout(cbk, delay, page, .{.repeat = true});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn _clearTimeout(self: *Window, id: u32, page: *Page) !void {
|
pub fn _clearTimeout(self: *Window, id: u32, page: *Page) !void {
|
||||||
const kv = self.timers.fetchRemove(id) orelse return;
|
const kv = self.timers.fetchRemove(id) orelse return;
|
||||||
try page.loop.cancel(kv.value.loop_id);
|
return page.loop.cancel(kv.value.loop_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn _clearInterval(self: *Window, id: u32, page: *Page) !void {
|
pub fn _clearInterval(self: *Window, id: u32, page: *Page) !void {
|
||||||
const kv = self.timers.fetchRemove(id) orelse return;
|
const kv = self.timers.fetchRemove(id) orelse return;
|
||||||
try page.loop.cancel(kv.value.loop_id);
|
return page.loop.cancel(kv.value.loop_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn _matchMedia(_: *const Window, media: []const u8, page: *Page) !MediaQueryList {
|
pub fn _matchMedia(_: *const Window, media: []const u8, page: *Page) !MediaQueryList {
|
||||||
@@ -216,10 +199,14 @@ pub const Window = struct {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn createTimeout(self: *Window, cbk: Function, delay_: ?u32, page: *Page, comptime repeat: bool) !u32 {
|
const CreateTimeoutOpts = struct {
|
||||||
|
repeat: bool = false,
|
||||||
|
animation_frame: bool = false,
|
||||||
|
};
|
||||||
|
fn createTimeout(self: *Window, cbk: Function, delay_: ?u32, page: *Page, comptime opts: CreateTimeoutOpts) !u32 {
|
||||||
const delay = delay_ orelse 0;
|
const delay = delay_ orelse 0;
|
||||||
if (delay > 5000) {
|
if (delay > 5000) {
|
||||||
log.warn(.user_script, "long timeout ignored", .{ .delay = delay, .interval = repeat });
|
log.warn(.user_script, "long timeout ignored", .{ .delay = delay, .interval = opts.repeat });
|
||||||
// self.timer_id is u30, so the largest value we can generate is
|
// self.timer_id is u30, so the largest value we can generate is
|
||||||
// 1_073_741_824. Returning 2_000_000_000 makes sure that clients
|
// 1_073_741_824. Returning 2_000_000_000 makes sure that clients
|
||||||
// can call cancelTimer/cancelInterval without breaking anything.
|
// can call cancelTimer/cancelInterval without breaking anything.
|
||||||
@@ -250,7 +237,8 @@ pub const Window = struct {
|
|||||||
.window = self,
|
.window = self,
|
||||||
.timer_id = timer_id,
|
.timer_id = timer_id,
|
||||||
.node = .{ .func = TimerCallback.run },
|
.node = .{ .func = TimerCallback.run },
|
||||||
.repeat = if (repeat) delay_ms else null,
|
.repeat = if (opts.repeat) delay_ms else null,
|
||||||
|
.animation_frame = opts.animation_frame,
|
||||||
};
|
};
|
||||||
callback.loop_id = try page.loop.timeout(delay_ms, &callback.node);
|
callback.loop_id = try page.loop.timeout(delay_ms, &callback.node);
|
||||||
|
|
||||||
@@ -300,13 +288,23 @@ const TimerCallback = struct {
|
|||||||
// if the event should be repeated
|
// if the event should be repeated
|
||||||
repeat: ?u63 = null,
|
repeat: ?u63 = null,
|
||||||
|
|
||||||
|
animation_frame: bool = false,
|
||||||
|
|
||||||
window: *Window,
|
window: *Window,
|
||||||
|
|
||||||
fn run(node: *Loop.CallbackNode, repeat_delay: *?u63) void {
|
fn run(node: *Loop.CallbackNode, repeat_delay: *?u63) void {
|
||||||
const self: *TimerCallback = @fieldParentPtr("node", node);
|
const self: *TimerCallback = @fieldParentPtr("node", node);
|
||||||
|
|
||||||
var result: Function.Result = undefined;
|
var result: Function.Result = undefined;
|
||||||
self.cbk.tryCall(void, .{}, &result) catch {
|
|
||||||
|
var call: anyerror!void = undefined;
|
||||||
|
if (self.animation_frame) {
|
||||||
|
call = self.cbk.tryCall(void, .{self.window.performance._now()}, &result);
|
||||||
|
} else {
|
||||||
|
call = self.cbk.tryCall(void, .{}, &result);
|
||||||
|
}
|
||||||
|
|
||||||
|
call catch {
|
||||||
log.debug(.user_script, "callback error", .{
|
log.debug(.user_script, "callback error", .{
|
||||||
.err = result.exception,
|
.err = result.exception,
|
||||||
.stack = result.stack,
|
.stack = result.stack,
|
||||||
|
|||||||
Reference in New Issue
Block a user