forked from ifreund/hello-zig-wayland
-
Notifications
You must be signed in to change notification settings - Fork 0
/
hello.zig
133 lines (110 loc) · 4.37 KB
/
hello.zig
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
const std = @import("std");
const os = std.os;
const wayland = @import("wayland");
const wl = wayland.client.wl;
const xdg = wayland.client.xdg;
const c = @cImport(@cInclude("linux/input-event-codes.h"));
const Context = struct {
shm: ?*wl.Shm = null,
compositor: ?*wl.Compositor = null,
wm_base: ?*xdg.WmBase = null,
xdg_toplevel: ?*xdg.Toplevel = null,
seat: ?*wl.Seat = null,
};
pub fn main() anyerror!void {
const display = try wl.Display.connect(null);
const registry = try display.getRegistry();
var context = Context{};
registry.setListener(*Context, registryListener, &context);
_ = try display.roundtrip();
const shm = context.shm orelse return error.NoWlShm;
const compositor = context.compositor orelse return error.NoWlCompositor;
const wm_base = context.wm_base orelse return error.NoXdgWmBase;
const buffer = blk: {
const width = 128;
const height = 128;
const stride = width * 4;
const size = stride * height;
const fd = try os.memfd_create("hello-zig-wayland", 0);
try os.ftruncate(fd, size);
const data = try os.mmap(null, size, os.PROT_READ | os.PROT_WRITE, os.MAP_SHARED, fd, 0);
std.mem.copy(u8, data, @embedFile("cat.bgra"));
const pool = try shm.createPool(fd, size);
defer pool.destroy();
break :blk try pool.createBuffer(0, width, height, stride, wl.Shm.Format.argb8888);
};
defer buffer.destroy();
const surface = try compositor.createSurface();
defer surface.destroy();
const xdg_surface = try wm_base.getXdgSurface(surface);
defer xdg_surface.destroy();
context.xdg_toplevel = try xdg_surface.getToplevel();
defer context.xdg_toplevel.?.destroy();
var running = true;
xdg_surface.setListener(*wl.Surface, xdgSurfaceListener, surface);
context.xdg_toplevel.?.setListener(*bool, xdgToplevelListener, &running);
surface.commit();
_ = try display.roundtrip();
surface.attach(buffer, 0, 0);
surface.commit();
while (running) _ = try display.dispatch();
}
fn registryListener(registry: *wl.Registry, event: wl.Registry.Event, context: *Context) void {
switch (event) {
.global => |global| {
if (std.cstr.cmp(global.interface, wl.Compositor.getInterface().name) == 0) {
context.compositor = registry.bind(global.name, wl.Compositor, 1) catch return;
} else if (std.cstr.cmp(global.interface, wl.Seat.getInterface().name) == 0) {
context.seat = registry.bind(global.name, wl.Seat, 1) catch return;
context.seat.?.setListener(*Context, seatListener, context);
} else if (std.cstr.cmp(global.interface, wl.Shm.getInterface().name) == 0) {
context.shm = registry.bind(global.name, wl.Shm, 1) catch return;
} else if (std.cstr.cmp(global.interface, xdg.WmBase.getInterface().name) == 0) {
context.wm_base = registry.bind(global.name, xdg.WmBase, 1) catch return;
}
},
.global_remove => {},
}
}
fn seatListener(seat: *wl.Seat, event: wl.Seat.Event, context: *Context) void {
switch (event) {
.capabilities => |data| {
if (data.capabilities.pointer) {
const pointer = seat.getPointer() catch return;
pointer.setListener(*Context, pointerListener, context);
}
},
.name => {},
}
}
fn pointerListener(pointer: *wl.Pointer, event: wl.Pointer.Event, context: *Context) void {
switch (event) {
.enter => {},
.leave => {},
.motion => {},
.button => |data| {
if (data.button == c.BTN_LEFT and data.state == wl.Pointer.ButtonState.pressed) {
context.xdg_toplevel.?.move(context.seat.?, data.serial);
}
},
.frame => {},
.axis => {},
.axis_source => {},
.axis_stop => {},
.axis_discrete => {},
}
}
fn xdgSurfaceListener(xdg_surface: *xdg.Surface, event: xdg.Surface.Event, surface: *wl.Surface) void {
switch (event) {
.configure => |configure| {
xdg_surface.ackConfigure(configure.serial);
surface.commit();
},
}
}
fn xdgToplevelListener(xdg_toplevel: *xdg.Toplevel, event: xdg.Toplevel.Event, running: *bool) void {
switch (event) {
.configure => {},
.close => running.* = false,
}
}