1const std = @import("std");
2const log = std.log;
3
4const wl = @import("wayland").client.wl;
5
6const Bar = @import("Bar.zig");
7const Input = @This();
8
9const state = &@import("root").state;
10
11globalName: u32,
12
13pointer: struct {
14 pointer: ?*wl.Pointer,
15 x: i32,
16 y: i32,
17 bar: ?*Bar,
18 surface: ?*wl.Surface,
19},
20
21pub fn create(name: u32) !*Input {
22 const self = try state.gpa.create(Input);
23 const seat = state.wayland.seat.?;
24
25 self.globalName = name;
26 self.pointer.pointer = null;
27 self.pointer.bar = null;
28 self.pointer.surface = null;
29
30 seat.setListener(*Input, listener, self);
31 return self;
32}
33
34pub fn destroy(self: *Input) void {
35 if (self.pointer.pointer) |pointer| {
36 pointer.release();
37 }
38 state.gpa.destroy(self);
39}
40
41fn listener(seat: *wl.Seat, event: wl.Seat.Event, input: *Input) void {
42 switch (event) {
43 .capabilities => |data| {
44 if (input.pointer.pointer) |pointer| {
45 pointer.release();
46 input.pointer.pointer = null;
47 }
48 if (data.capabilities.pointer) {
49 input.pointer.pointer = seat.getPointer() catch |err| {
50 log.err("cannot obtain seat pointer: {s}", .{@errorName(err)});
51 return;
52 };
53 input.pointer.pointer.?.setListener(
54 *Input,
55 pointerListener,
56 input,
57 );
58 }
59 },
60 .name => {},
61 }
62}
63
64fn pointerListener(
65 _: *wl.Pointer,
66 event: wl.Pointer.Event,
67 input: *Input,
68) void {
69 switch (event) {
70 .enter => |data| {
71 input.pointer.x = data.surface_x.toInt();
72 input.pointer.y = data.surface_y.toInt();
73 const bar = state.wayland.findBar(data.surface);
74 input.pointer.bar = bar;
75 input.pointer.surface = data.surface;
76 },
77 .leave => |_| {
78 input.pointer.bar = null;
79 input.pointer.surface = null;
80 },
81 .motion => |data| {
82 input.pointer.x = data.surface_x.toInt();
83 input.pointer.y = data.surface_y.toInt();
84 },
85 .button => |data| {
86 if (data.state != .pressed) return;
87 if (input.pointer.bar) |bar| {
88 if (!bar.configured) return;
89
90 const tagsSurface = bar.tags.surface;
91 if (input.pointer.surface != tagsSurface) return;
92
93 const x: u32 = @intCast(input.pointer.x);
94 if (x < bar.height * @as(u16, bar.monitor.tags.tags.len)) {
95 bar.monitor.tags.handleClick(x) catch |err| {
96 log.err("handleClick failed for monitor {}: {s}",
97 .{bar.monitor.globalName, @errorName(err)});
98 return;
99 };
100 }
101 }
102 },
103 else => {},
104 }
105}