summaryrefslogtreecommitdiff
path: root/source/base/base_platform_linux_wayland.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/base/base_platform_linux_wayland.cpp')
-rw-r--r--source/base/base_platform_linux_wayland.cpp200
1 files changed, 169 insertions, 31 deletions
diff --git a/source/base/base_platform_linux_wayland.cpp b/source/base/base_platform_linux_wayland.cpp
index cd1fde8..772080b 100644
--- a/source/base/base_platform_linux_wayland.cpp
+++ b/source/base/base_platform_linux_wayland.cpp
@@ -1,55 +1,193 @@
1// https://gaultier.github.io/blog/wayland_from_scratch.html#creating-a-registry
1// TODO: replace unix_get_env with a generic macro 2// TODO: replace unix_get_env with a generic macro
2 3
3//- wayland
4internal void wayland_display_connect(MemArena *arena) {
5
6 4
7ScratchArena env_scratch = scratch_start(arena);
8 5
6//- wayland
7internal int wayland_display_connect(MemArena *arena) {
9 8
10 String8 str8_xdg_runtime_dir = unix_get_env("XDG_RUNTIME_DIR"); 9 String8 str8_xdg_runtime_dir = unix_get_env("XDG_RUNTIME_DIR");
11 char *xdg_runtime_dir = null_terminate(arena, &str8_xdg_runtime_dir); 10 char *xdg_runtime_dir = null_terminate(arena, &str8_xdg_runtime_dir);
11 sockaddr_un addr = {};
12 u64 socket_path_len = 0;
12 13
13u64 xdg_runtime_dir_len = str8_xdg_runtime_dir.size; 14// copy the xdg_runtime_dir value to the beginning of the bfufer
15{
16 addr.sun_family = AF_UNIX;
17 MemCpy(addr.sun_path, xdg_runtime_dir, str8_xdg_runtime_dir.size);
18 socket_path_len += str8_xdg_runtime_dir.size;
19 addr.sun_path[socket_path_len++] = '/'; // add an ending slash
20}
14 21
15 sockaddr_un addr = {}; 22 String8 str8_wayland_display_value = unix_get_env("WAYLAND_DISPLAY");
16addr.sun_family = AF_UNIX; 23Assert(str8_wayland_display_value.size != 0);
24 char *wayland_display = null_terminate(arena, &str8_wayland_display_value);
17 25
18 Assert(xdg_runtime_dir_len <= cstring8_length((u8 *)addr.sun_path)); 26 if(wayland_display == NULL)
27 {
28 const char *wayland_display_default = "wayland-0";
29 u64 wayland_display_default_len = cstring8_length((u8 *)wayland_display_default);
30 MemCpy(addr.sun_path, wayland_display_default, wayland_display_default_len);
31 }
32 else
33 {
34 MemCpy(addr.sun_path + str8_xdg_runtime_dir.size + 1, wayland_display, str8_wayland_display_value.size);
35}
19 36
20u64 socket_path_len = 0; 37 int fd = socket(AF_UNIX, SOCK_STREAM, 0);
21MemCpy(addr.sun_path, xdg_runtime_dir, str8_xdg_runtime_dir.size);
22socket_path_len += xdg_runtime_dir_len;
23 38
39#if DEBUG // helps to read those errors? i guess i can just read stderr?
24 40
25addr.sun_path[socket_path_len++] = '/';
26String8 str8_wayland_display_value = unix_get_env("WAYLAND_DISPLAY");
27char *wayland_display = null_terminate(arena, &str8_wayland_display_value);
28if(wayland_display == NULL)
29{
30const char *wayland_display_default = "wayland-0";
31u64 wayland_display_default_len = cstring8_length((u8 *)wayland_display_default);
32MemCpy(addr.sun_path + socket_path_len, wayland_display_default, wayland_display_default_len);
33}
34else
35{
36u64 wayland_display_len = cstring8_length((u8 *)wayland_display);
37MemCpy(addr.sun_path + socket_path_len, wayland_display, wayland_display_len);
38socket_path_len += wayland_display_len;
39}
40 41
41scratch_end(&env_scratch);
42 42
43int fd = socket(AF_UNIX, SOCK_STREAM, 0);
44if(fd == -1) 43if(fd == -1)
45{ 44{
46exit(1); 45perror("failed to open socket");
47} 46}
48 47
48
49if(connect(fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) 49if(connect(fd, (struct sockaddr *)&addr, sizeof(addr)) == -1)
50{ 50{
51exit(1); 51perror("failed to connect to socket");
52
53}
54
55#endif
56
57
58 AssertLog((fd != -1), "failed to open socket\n");
59 AssertLog((connect(fd, (struct sockaddr *)&addr, sizeof(addr)) == -1), "failed to connect to socket\n");
60
61return fd;
62
63}
64
65
66//- helper functions
67
68internal void buf_write_u32(char *buf, u64 *buf_size, u64 buf_cap,
69 u32 x) {
70 Assert(*buf_size + sizeof(x) <= buf_cap);
71 Assert(((size_t)buf + *buf_size) % sizeof(x) == 0);
72
73 *(u32 *)(buf + *buf_size) = x;
74 *buf_size += sizeof(x);
75}
76
77internal void buf_write_u16(char *buf, u64 *buf_size, u64 buf_cap,
78 u16 x) {
79 Assert(*buf_size + sizeof(x) <= buf_cap);
80 Assert(((size_t)buf + *buf_size) % sizeof(x) == 0);
81
82 *(u16 *)(buf + *buf_size) = x;
83 *buf_size += sizeof(x);
84}
85
86internal void buf_write_string(char *buf, u64 *buf_size, u64 buf_cap,
87 char *src, u32 src_len) {
88 Assert(*buf_size + src_len <= buf_cap);
89
90 buf_write_u32(buf, buf_size, buf_cap, src_len);
91 memcpy(buf + *buf_size, src, roundup_4(src_len));
92 *buf_size += roundup_4(src_len);
93}
94
95internal u32 buf_read_u32(char **buf, u64 *buf_size) {
96 Assert(*buf_size >= sizeof(u32));
97 Assert((size_t)*buf % sizeof(u32) == 0);
98
99 u32 res = *(u32 *)(*buf);
100 *buf += sizeof(res);
101 *buf_size -= sizeof(res);
102
103 return res;
104}
105
106internal u16 buf_read_u16(char **buf, u64 *buf_size) {
107 Assert(*buf_size >= sizeof(u16));
108 Assert((size_t)*buf % sizeof(u16) == 0);
109
110 u16 res = *(u16 *)(*buf);
111 *buf += sizeof(res);
112 *buf_size -= sizeof(res);
113
114 return res;
115}
116
117internal void buf_read_n(char **buf, u64 *buf_size, char *dst, u64 n) {
118 Assert(*buf_size >= n);
119
120 memcpy(dst, *buf, n);
121
122 *buf += n;
123 *buf_size -= n;
52} 124}
53 125
126global_variable u64 wayland_current_id = 1;
54 127
55} \ No newline at end of file 128internal u32 wayland_wl_display_get_registry(int fd) {
129 uint64_t msg_size = 0;
130 char msg[128] = "";
131 buf_write_u32(msg, &msg_size, sizeof(msg), wayland_display_object_id);
132
133 buf_write_u16(msg, &msg_size, sizeof(msg),
134 wayland_wl_display_get_registry_opcode);
135
136 u16 msg_announced_size = wayland_header_size + sizeof(wayland_current_id);
137 Assert(roundup_4(msg_announced_size) == msg_announced_size);
138 buf_write_u16(msg, &msg_size, sizeof(msg), msg_announced_size);
139
140 wayland_current_id++;
141 buf_write_u32(msg, &msg_size, sizeof(msg), wayland_current_id);
142
143 if ((s64)msg_size != send(fd, msg, msg_size, MSG_DONTWAIT))
144 exit(1);
145
146 Log("-> wl_display@%u.get_registry: wl_registry=%u\n",
147 wayland_display_object_id, wayland_current_id);
148
149 return wayland_current_id;
150}
151
152
153
154 internal void create_shared_memory_file(u64 size, state_t *state) {
155 char name[255] = "/";
156 for (u64 index = 1; index < cstring8_length((u8 *)name); ++index) {
157 name[index] = ((double)rand()) / (double)RAND_MAX * 26 + 'a';
158 }
159
160 int fd = shm_open(name, O_RDWR | O_EXCL | O_CREAT, 0600);
161 AssertLog((fd != -1), "Failed to open buffer for shared memory.");
162
163 Assert(shm_unlink(name) != -1);
164
165 AssertLog((ftruncate(fd, size) != -1), "Failed to truncate buffer.");
166
167 state->shm_pool_data = (u8 *)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
168 Assert((void*)-1 != state->shm_pool_data);
169 Assert(state->shm_pool_data != NULL);
170 state->shm_fd = fd;
171}
172
173 internal void wayland_handle_message(int fd, state_t *state, char **msg,
174 uint64_t *msg_len) {
175 Assert(*msg_len >= 8);
176
177 u32 object_id = buf_read_u32(msg, msg_len);
178 Assert(object_id <= wayland_current_id);
179
180 u16 opcode = buf_read_u16(msg, msg_len);
181
182 u16 announced_size = buf_read_u16(msg, msg_len);
183 Assert(roundup_4(announced_size) <= announced_size);
184
185 u32 header_size = sizeof(object_id) + sizeof(opcode) + sizeof(announced_size);
186Assert(announced_size <= header_size + *msg_len);
187
188 if (object_id == state->wl_registry &&
189 opcode == wayland_wl_registry_event_global) {
190 // TODO
191 }
192 // Following: Lots of `if (opcode == ...) {... } else if (opcode = ...) { ... } [...]`
193}