mirror of
https://mzte.de/git/LordMZTE/dotfiles.git
synced 2024-05-18 15:04:19 +02:00
wlbg: completely remove draw handler from event loop in idle state
the process is completely blocked with no interaction happening
This commit is contained in:
parent
733b7cf4ce
commit
8a2e617f39
41
scripts/wlbg/src/DrawTimerHandler.zig
Normal file
41
scripts/wlbg/src/DrawTimerHandler.zig
Normal file
|
@ -0,0 +1,41 @@
|
|||
const std = @import("std");
|
||||
const xev = @import("xev");
|
||||
|
||||
const options = @import("options.zig");
|
||||
|
||||
loop: *xev.Loop,
|
||||
|
||||
/// Completion of the main redraw timer
|
||||
completion: *xev.Completion,
|
||||
|
||||
/// Contains a bool for each output, true if needs redraw
|
||||
should_redraw: []bool,
|
||||
|
||||
const DrawTimerHandler = @This();
|
||||
|
||||
pub fn nextAction(self: *DrawTimerHandler) xev.CallbackAction {
|
||||
for (self.should_redraw) |ro|
|
||||
if (ro) return .rearm;
|
||||
return .disarm;
|
||||
}
|
||||
|
||||
pub fn maybeWake(self: *DrawTimerHandler) void {
|
||||
if (self.completion.flags.state == .dead and self.nextAction() == .rearm) {
|
||||
self.resetTimer();
|
||||
self.loop.add(self.completion);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn resetTimer(self: *DrawTimerHandler) void {
|
||||
const next_time = self.loop.now() + 1000 / options.fps;
|
||||
self.completion.op.timer.reset = .{
|
||||
.tv_sec = @divTrunc(next_time, std.time.ms_per_s),
|
||||
.tv_nsec = @mod(next_time, std.time.ms_per_s) * std.time.ns_per_ms,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn damage(self: *DrawTimerHandler, idx: usize) void {
|
||||
self.should_redraw[idx] = true;
|
||||
self.maybeWake();
|
||||
}
|
||||
|
|
@ -4,6 +4,7 @@ const c = @import("ffi.zig").c;
|
|||
const glutil = @import("glutil.zig");
|
||||
const options = @import("options.zig");
|
||||
|
||||
const DrawTimerHandler = @import("DrawTimerHandler.zig");
|
||||
const OutputInfo = @import("OutputInfo.zig");
|
||||
const OutputWindow = @import("OutputWindow.zig");
|
||||
const PointerState = @import("PointerState.zig");
|
||||
|
@ -164,8 +165,11 @@ pub fn preDraw(
|
|||
pointer_state: *PointerState,
|
||||
outputs: []const OutputWindow,
|
||||
infos: []const OutputInfo,
|
||||
dth: *DrawTimerHandler,
|
||||
) !void {
|
||||
for (self.cursor_positions, self.should_redraw, infos, outputs) |*pos, *redraw, inf, outp| {
|
||||
for (self.cursor_positions, infos, outputs, 0..) |*pos, inf, outp, i| {
|
||||
const lerp_amt = std.math.clamp(@as(f32, @floatFromInt(std.math.clamp(dt, 0, 10))) / 150.0, 0.0, 1.0);
|
||||
|
||||
const target = if (pointer_state.surface == outp.surface)
|
||||
.{ pointer_state.x, pointer_state.y }
|
||||
else
|
||||
|
@ -174,16 +178,16 @@ pub fn preDraw(
|
|||
const new_x: c_int = @intFromFloat(std.math.lerp(
|
||||
@as(f32, @floatFromInt(pos[0])),
|
||||
@as(f32, @floatFromInt(target[0])),
|
||||
std.math.clamp(@as(f32, @floatFromInt(dt)) / 250.0, 0.0, 1.0),
|
||||
lerp_amt,
|
||||
));
|
||||
const new_y: c_int = @intFromFloat(std.math.lerp(
|
||||
@as(f32, @floatFromInt(pos[1])),
|
||||
@as(f32, @floatFromInt(target[1])),
|
||||
std.math.clamp(@as(f32, @floatFromInt(dt)) / 250.0, 0.0, 1.0),
|
||||
lerp_amt,
|
||||
));
|
||||
|
||||
if (new_x != pos[0] or new_y != pos[1])
|
||||
redraw.* = true;
|
||||
dth.damage(i);
|
||||
|
||||
pos[0] = new_x;
|
||||
pos[1] = new_y;
|
||||
|
@ -197,15 +201,13 @@ pub fn draw(
|
|||
output_idx: usize,
|
||||
outputs: []const OutputWindow,
|
||||
infos: []const OutputInfo,
|
||||
dth: *DrawTimerHandler,
|
||||
) !void {
|
||||
self.time += dt;
|
||||
dth.should_redraw[output_idx] = false;
|
||||
c.glBindFramebuffer(c.GL_FRAMEBUFFER, 0); // use default framebuffer
|
||||
c.glUseProgram(self.main_shader_program);
|
||||
|
||||
if (!self.should_redraw[output_idx])
|
||||
return;
|
||||
self.should_redraw[output_idx] = false;
|
||||
|
||||
const vertices = [_]f32{
|
||||
-1.0, -1.0, 0.0, 0.0, 0.0,
|
||||
1.0, -1.0, 0.0, 1.0, 0.0,
|
||||
|
|
|
@ -5,6 +5,7 @@ const wayland = @import("wayland");
|
|||
const c = @import("ffi.zig").c;
|
||||
const options = @import("options.zig");
|
||||
|
||||
const DrawTimerHandler = @import("DrawTimerHandler.zig");
|
||||
const Gfx = @import("Gfx.zig");
|
||||
const Globals = @import("Globals.zig");
|
||||
const OutputInfo = @import("OutputInfo.zig");
|
||||
|
@ -130,15 +131,32 @@ pub fn main() !void {
|
|||
}
|
||||
defer for (output_windows) |output| output.deinit(egl_ctx);
|
||||
|
||||
var r_timer_completion: xev.Completion = undefined;
|
||||
var r_timer = try xev.Timer.init();
|
||||
defer r_timer.deinit();
|
||||
|
||||
var dth = DrawTimerHandler{
|
||||
.should_redraw = try std.heap.c_allocator.alloc(bool, output_info.len),
|
||||
.completion = &r_timer_completion,
|
||||
.loop = &loop,
|
||||
};
|
||||
defer std.heap.c_allocator.free(dth.should_redraw);
|
||||
|
||||
var pointer_state = PointerState{
|
||||
.surface = null,
|
||||
.x = 0,
|
||||
.y = 0,
|
||||
};
|
||||
|
||||
var pointer_listener_data = PointerListenerData{
|
||||
.pstate = &pointer_state,
|
||||
.outputs = output_windows,
|
||||
.dth = &dth,
|
||||
};
|
||||
|
||||
const pointer = try globs.seat.getPointer();
|
||||
defer pointer.destroy();
|
||||
pointer.setListener(*PointerState, pointerListener, &pointer_state);
|
||||
pointer.setListener(*PointerListenerData, pointerListener, &pointer_listener_data);
|
||||
|
||||
const base_offset: [2]i32 = off: {
|
||||
if (comptime options.multihead_mode == .individual) break :off .{ 0, 0 };
|
||||
|
@ -180,6 +198,7 @@ pub fn main() !void {
|
|||
.last_time = loop.now(),
|
||||
.base_offset = base_offset,
|
||||
.pointer_state = &pointer_state,
|
||||
.dth = &dth,
|
||||
};
|
||||
|
||||
var rbg_timer_completion: xev.Completion = undefined;
|
||||
|
@ -195,10 +214,6 @@ pub fn main() !void {
|
|||
renderBackgroundCb,
|
||||
);
|
||||
|
||||
var r_timer_completion: xev.Completion = undefined;
|
||||
var r_timer = try xev.Timer.init();
|
||||
defer r_timer.deinit();
|
||||
|
||||
r_timer.run(
|
||||
&loop,
|
||||
&r_timer_completion,
|
||||
|
@ -228,6 +243,7 @@ const RenderData = struct {
|
|||
last_time: isize,
|
||||
base_offset: [2]c_int,
|
||||
pointer_state: *PointerState,
|
||||
dth: *DrawTimerHandler,
|
||||
};
|
||||
|
||||
fn renderCb(
|
||||
|
@ -236,19 +252,21 @@ fn renderCb(
|
|||
completion: *xev.Completion,
|
||||
result: xev.Timer.RunError!void,
|
||||
) xev.CallbackAction {
|
||||
_ = completion;
|
||||
result catch unreachable;
|
||||
|
||||
const now = loop.now();
|
||||
const delta_time = now - data.?.last_time;
|
||||
data.?.last_time = now;
|
||||
|
||||
resetXevTimerCompletion(completion, now, 1000 / options.fps);
|
||||
data.?.dth.resetTimer();
|
||||
|
||||
data.?.gfx.preDraw(
|
||||
delta_time,
|
||||
data.?.pointer_state,
|
||||
data.?.outputs,
|
||||
data.?.output_info,
|
||||
data.?.dth,
|
||||
) catch |e| {
|
||||
std.log.err("running preDraw: {}", .{e});
|
||||
loop.stop();
|
||||
|
@ -256,6 +274,9 @@ fn renderCb(
|
|||
};
|
||||
|
||||
for (data.?.outputs, 0..) |output, i| {
|
||||
if (!data.?.dth.should_redraw[i])
|
||||
continue;
|
||||
|
||||
if (c.eglMakeCurrent(
|
||||
data.?.egl_dpy,
|
||||
output.egl_surface,
|
||||
|
@ -273,6 +294,7 @@ fn renderCb(
|
|||
i,
|
||||
data.?.outputs,
|
||||
data.?.output_info,
|
||||
data.?.dth,
|
||||
) catch |e| {
|
||||
std.log.err("drawing: {}", .{e});
|
||||
loop.stop();
|
||||
|
@ -280,7 +302,7 @@ fn renderCb(
|
|||
};
|
||||
}
|
||||
|
||||
return .rearm;
|
||||
return data.?.dth.nextAction();
|
||||
}
|
||||
|
||||
fn renderBackgroundCb(
|
||||
|
@ -359,14 +381,43 @@ fn xdgOutputListener(_: *zxdg.OutputV1, ev: zxdg.OutputV1.Event, info: *OutputIn
|
|||
}
|
||||
}
|
||||
|
||||
fn pointerListener(_: *wl.Pointer, ev: wl.Pointer.Event, state: *PointerState) void {
|
||||
const PointerListenerData = struct {
|
||||
pstate: *PointerState,
|
||||
outputs: []const OutputWindow,
|
||||
dth: *DrawTimerHandler,
|
||||
|
||||
fn damageCurrentWindow(self: *PointerListenerData) !void {
|
||||
if (self.pstate.surface) |ps| {
|
||||
for (self.outputs, 0..) |o, i| {
|
||||
if (ps == o.surface) {
|
||||
self.dth.damage(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
fn pointerListener(_: *wl.Pointer, ev: wl.Pointer.Event, d: *PointerListenerData) void {
|
||||
switch (ev) {
|
||||
.motion => |motion| {
|
||||
state.x = motion.surface_x.toInt();
|
||||
state.y = motion.surface_y.toInt();
|
||||
d.pstate.x = motion.surface_x.toInt();
|
||||
d.pstate.y = motion.surface_y.toInt();
|
||||
d.damageCurrentWindow() catch |e| {
|
||||
std.log.err("unable to damage window: {}", .{e});
|
||||
};
|
||||
},
|
||||
.enter => |enter| {
|
||||
d.pstate.surface = enter.surface;
|
||||
d.damageCurrentWindow() catch |e| {
|
||||
std.log.err("unable to damage window: {}", .{e});
|
||||
};
|
||||
},
|
||||
.leave => {
|
||||
d.damageCurrentWindow() catch |e| {
|
||||
std.log.err("unable to damage window: {}", .{e});
|
||||
};
|
||||
d.pstate.surface = null;
|
||||
},
|
||||
.enter => |enter| state.surface = enter.surface,
|
||||
.leave => state.surface = null,
|
||||
else => {},
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue