aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIsaac Freund <ifreund@ifreund.xyz>2020-03-22 00:52:09 +0100
committerIsaac Freund <ifreund@ifreund.xyz>2020-03-22 00:52:09 +0100
commit76ed2a72a8b83333e39b0ce7a04e0a519e4378e6 (patch)
tree6472d0f427cc793cffd42a0b012458f7431b2431
parent57ab110f43efd2681fd61872820ac942b8f5bcd3 (diff)
downloadriver-76ed2a72a8b83333e39b0ce7a04e0a519e4378e6.tar.gz
river-76ed2a72a8b83333e39b0ce7a04e0a519e4378e6.tar.xz
Use std.ArrayList over wl_list and fix bugs
This is now a working hello world!
-rw-r--r--src/main.zig89
1 files changed, 46 insertions, 43 deletions
diff --git a/src/main.zig b/src/main.zig
index 0aa5fce..e2982b3 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -6,10 +6,9 @@ const Server = struct {
wl_display: *c.wl_display,
backend: *c.wlr_backend,
renderer: *c.wlr_renderer,
-
xdg_shell: *c.wlr_xdg_shell,
new_xdg_surface: c.wl_listener,
- views: c.wl_list,
+ views: std.ArrayList(View),
cursor: *c.wlr_cursor,
cursor_mgr: *c.wlr_xcursor_manager,
@@ -32,19 +31,17 @@ const Server = struct {
resize_edges: u32,
output_layout: *c.wlr_output_layout,
- outputs: c.wl_list,
+ outputs: std.ArrayList(Output),
new_output: c.wl_listener,
};
const Output = struct {
- link: c.wl_list,
server: *Server,
wlr_output: *c.wlr_output,
frame: c.wl_listener,
};
const View = struct {
- link: c.wl_list,
server: *Server,
xdg_surface: *c.wlr_xdg_surface,
map: c.wl_listener,
@@ -175,11 +172,7 @@ fn output_frame(listener: [*c]c.wl_listener, data: ?*c_void) callconv(.C) void {
// Each subsequent window we render is rendered on top of the last. Because
// our view list is ordered front-to-back, we iterate over it backwards.
- // wl_list_for_each_reverse(view, &output.*.server.*.views, link) {
-
- var view = @fieldParentPtr(View, "link", output.*.server.*.views.prev);
-
- while (&view.*.link != &output.*.server.*.views) {
+ for (output.*.server.views.span()) |*view| {
if (!view.*.mapped) {
// An unmapped view should not be rendered.
continue;
@@ -193,9 +186,6 @@ fn output_frame(listener: [*c]c.wl_listener, data: ?*c_void) callconv(.C) void {
// This calls our render_surface function for each surface among the
// xdg_surface's toplevel and popups.
c.wlr_xdg_surface_for_each_surface(view.*.xdg_surface, render_surface, &rdata);
-
- // Move to next item in list
- view = @fieldParentPtr(View, "link", view.*.link.prev);
}
// Hardware cursors are rendered by the GPU on a separate plane, and can be
@@ -234,13 +224,18 @@ fn server_new_output(listener: [*c]c.wl_listener, data: ?*c_void) callconv(.C) v
}
// Allocates and configures our state for this output
- var output = std.heap.c_allocator.create(Output) catch unreachable;
+ server.*.outputs.append(Output{
+ .server = undefined,
+ .wlr_output = undefined,
+ .frame = undefined,
+ }) catch unreachable;
+ var output = &server.*.outputs.span()[server.*.outputs.span().len - 1];
output.*.wlr_output = wlr_output;
output.*.server = server;
+
// Sets up a listener for the frame notify event.
output.*.frame.notify = output_frame;
c.wl_signal_add(&wlr_output.*.events.frame, &output.*.frame);
- c.wl_list_insert(&server.*.outputs, &output.*.link);
// Adds this to the output layout. The add_auto function arranges outputs
// from left-to-right in the order they appear. A more sophisticated
@@ -272,18 +267,26 @@ fn focus_view(view: *View, surface: *c.wlr_surface) void {
_ = c.wlr_xdg_toplevel_set_activated(prev_xdg_surface, false);
}
+ // Find the index
+ const idx = for (server.*.views.span()) |*v, i| {
+ if (v == view) {
+ break i;
+ }
+ } else unreachable;
+
// Move the view to the front
- c.wl_list_remove(&view.*.link);
- c.wl_list_insert(&server.*.views, &view.*.link);
+ server.*.views.append(server.*.views.orderedRemove(idx)) catch unreachable;
+
+ var moved_view = &server.*.views.span()[server.*.views.span().len - 1];
// Activate the new surface
- _ = c.wlr_xdg_toplevel_set_activated(view.*.xdg_surface, true);
+ _ = c.wlr_xdg_toplevel_set_activated(moved_view.*.xdg_surface, true);
// Tell the seat to have the keyboard enter this surface. wlroots will keep
// track of this and automatically send key events to the appropriate
// clients without additional work on your part.
var keyboard = c.wlr_seat_get_keyboard(seat);
- c.wlr_seat_keyboard_notify_enter(seat, view.*.xdg_surface.*.surface, &keyboard.*.keycodes, keyboard.*.num_keycodes, &keyboard.*.modifiers);
+ c.wlr_seat_keyboard_notify_enter(seat, moved_view.*.xdg_surface.*.surface, &keyboard.*.keycodes, keyboard.*.num_keycodes, &keyboard.*.modifiers);
}
fn xdg_surface_map(listener: [*c]c.wl_listener, data: ?*c_void) callconv(.C) void {
@@ -294,14 +297,19 @@ fn xdg_surface_map(listener: [*c]c.wl_listener, data: ?*c_void) callconv(.C) voi
}
fn xdg_surface_unmap(listener: [*c]c.wl_listener, data: ?*c_void) callconv(.C) void {
- var view = @fieldParentPtr(View, "map", listener);
+ var view = @fieldParentPtr(View, "unmap", listener);
view.*.mapped = false;
}
fn xdg_surface_destroy(listener: [*c]c.wl_listener, data: ?*c_void) callconv(.C) void {
- var view = @fieldParentPtr(View, "map", listener);
- c.wl_list_remove(&view.*.link);
- // TODO: free the memory
+ var view = @fieldParentPtr(View, "destroy", listener);
+ var server = view.*.server;
+ const idx = for (server.*.views.span()) |*v, i| {
+ if (v == view) {
+ break i;
+ }
+ } else return;
+ _ = server.*.views.orderedRemove(idx);
}
fn xdg_toplevel_request_move(listener: [*c]c.wl_listener, data: ?*c_void) callconv(.C) void {
@@ -323,7 +331,9 @@ fn server_new_xdg_surface(listener: [*c]c.wl_listener, data: ?*c_void) callconv(
}
// Allocate a View for this surface
- var view = std.heap.c_allocator.create(View) catch unreachable;
+ server.*.views.append(undefined) catch unreachable;
+ var view = &server.*.views.span()[server.*.views.span().len - 1];
+
view.*.server = server;
view.*.xdg_surface = xdg_surface;
@@ -343,9 +353,6 @@ fn server_new_xdg_surface(listener: [*c]c.wl_listener, data: ?*c_void) callconv(
view.*.request_resize.notify = xdg_toplevel_request_resize;
c.wl_signal_add(&toplevel.*.events.request_resize, &view.*.request_resize);
-
- // Add it to the list of views.
- c.wl_list_insert(&server.*.views, &view.*.link);
}
fn keyboard_handle_modifiers(listener: [*c]c.wl_listener, data: ?*c_void) callconv(.C) void {
@@ -373,14 +380,14 @@ fn handle_keybinding(server: *Server, sym: c.xkb_keysym_t) bool {
c.XKB_KEY_Escape => c.wl_display_terminate(server.*.wl_display),
c.XKB_KEY_F1 => {
// Cycle to the next view
- if (c.wl_list_length(&server.*.views) > 1) {
- const current_view = @fieldParentPtr(View, "link", server.*.views.next);
- const next_view = @fieldParentPtr(View, "link", current_view.*.link.next);
- focus_view(next_view, next_view.*.xdg_surface.*.surface);
- // Move the previous view to the end of the list
- c.wl_list_remove(&current_view.*.link);
- c.wl_list_insert(server.*.views.prev, &current_view.*.link);
- }
+ //if (c.wl_list_length(&server.*.views) > 1) {
+ // const current_view = @fieldParentPtr(View, "link", server.*.views.next);
+ // const next_view = @fieldParentPtr(View, "link", current_view.*.link.next);
+ // focus_view(next_view, next_view.*.xdg_surface.*.surface);
+ // // Move the previous view to the end of the list
+ // c.wl_list_remove(&current_view.*.link);
+ // c.wl_list_insert(server.*.views.prev, &current_view.*.link);
+ //}
},
else => return false,
}
@@ -536,15 +543,10 @@ fn view_at(view: *View, lx: f64, ly: f64, surface: *?*c.wlr_surface, sx: *f64, s
fn desktop_view_at(server: *Server, lx: f64, ly: f64, surface: *?*c.wlr_surface, sx: *f64, sy: *f64) ?*View {
// This iterates over all of our surfaces and attempts to find one under the
// cursor. This relies on server.*.views being ordered from top-to-bottom.
-
- //wl_list_for_each(view, &server->views, link) {
- var view = @fieldParentPtr(View, "link", server.*.views.next);
- while (&view.*.link != &server.*.views) {
+ for (server.*.views.span()) |*view| {
if (view_at(view, lx, ly, surface, sx, sy)) {
return view;
}
-
- view = @fieldParentPtr(View, "link", view.*.link.next);
}
return null;
}
@@ -755,7 +757,8 @@ pub fn main() !void {
// Creates an output layout, which a wlroots utility for working with an
// arrangement of screens in a physical layout.
server.output_layout = c.wlr_output_layout_create();
- c.wl_list_init(&server.outputs);
+
+ server.outputs = std.ArrayList(Output).init(std.heap.c_allocator);
// Configure a listener to be notified when new outputs are available on the
// backend.
@@ -765,7 +768,7 @@ pub fn main() !void {
// Set up our list of views and the xdg-shell. The xdg-shell is a Wayland
// protocol which is used for application windows.
// https://drewdevault.com/2018/07/29/Wayland-shells.html
- c.wl_list_init(&server.views);
+ server.views = std.ArrayList(View).init(std.heap.c_allocator);
server.xdg_shell = c.wlr_xdg_shell_create(server.wl_display);
server.new_xdg_surface.notify = server_new_xdg_surface;
c.wl_signal_add(&server.xdg_shell.*.events.new_surface, &server.new_xdg_surface);