Hack around @cImport() not handling flexible arrays
This commit is contained in:
parent
e1d1683c3f
commit
57ab110f43
5 changed files with 342 additions and 25 deletions
|
@ -17,6 +17,8 @@ pub fn build(b: *Builder) void {
|
|||
exe.addIncludeDir("protocol");
|
||||
exe.linkLibC();
|
||||
exe.addIncludeDir("/usr/include/pixman-1");
|
||||
exe.addCSourceFile("include/render.c", &[_][]const u8{"-std=c99"});
|
||||
exe.addIncludeDir(".");
|
||||
//exe.linkSystemLibrary("pixman");
|
||||
exe.linkSystemLibrary("wayland-server");
|
||||
exe.linkSystemLibrary("wlroots");
|
||||
|
|
20
include/render.c
Normal file
20
include/render.c
Normal file
|
@ -0,0 +1,20 @@
|
|||
#define WLR_USE_UNSTABLE
|
||||
#include <wlr/backend.h>
|
||||
#include <wlr/render/wlr_renderer.h>
|
||||
|
||||
struct wlr_backend *zag_wlr_backend_autocreate(struct wl_display *display) {
|
||||
return wlr_backend_autocreate(display, NULL);
|
||||
}
|
||||
|
||||
struct wlr_renderer *zag_wlr_backend_get_renderer(struct wlr_backend *backend) {
|
||||
return wlr_backend_get_renderer(backend);
|
||||
}
|
||||
|
||||
bool zag_wlr_backend_start(struct wlr_backend *backend) {
|
||||
return wlr_backend_start(backend);
|
||||
}
|
||||
|
||||
void zag_wlr_backend_destroy(struct wlr_backend *backend) {
|
||||
zag_wlr_backend_destroy(backend);
|
||||
}
|
||||
|
27
include/render.h
Normal file
27
include/render.h
Normal file
|
@ -0,0 +1,27 @@
|
|||
#ifndef ZAG_RENDER_H
|
||||
#define ZAG_RENDER_H
|
||||
|
||||
#include <wlr/backend/session.h>
|
||||
|
||||
struct wlr_backend_impl;
|
||||
|
||||
struct wlr_backend {
|
||||
const struct wlr_backend_impl *impl;
|
||||
|
||||
struct {
|
||||
/** Raised when destroyed, passed the wlr_backend reference */
|
||||
struct wl_signal destroy;
|
||||
/** Raised when new inputs are added, passed the wlr_input_device */
|
||||
struct wl_signal new_input;
|
||||
/** Raised when new outputs are added, passed the wlr_output */
|
||||
struct wl_signal new_output;
|
||||
} events;
|
||||
};
|
||||
|
||||
struct wlr_backend *zag_wlr_backend_autocreate(struct wl_display *display);
|
||||
struct wlr_renderer *zag_wlr_backend_get_renderer(struct wlr_backend *backend);
|
||||
bool zag_wlr_backend_start(struct wlr_backend *backend);
|
||||
void zag_wlr_backend_destroy(struct wlr_backend *backend);
|
||||
|
||||
|
||||
#endif
|
|
@ -5,8 +5,8 @@ pub const c = @cImport({
|
|||
@cInclude("time.h");
|
||||
@cInclude("stdlib.h");
|
||||
@cInclude("wayland-server-core.h");
|
||||
@cInclude("wlr/backend.h");
|
||||
@cInclude("wlr/render/wlr_renderer.h");
|
||||
//@cInclude("wlr/backend.h");
|
||||
//@cInclude("wlr/render/wlr_renderer.h");
|
||||
@cInclude("wlr/types/wlr_cursor.h");
|
||||
@cInclude("wlr/types/wlr_compositor.h");
|
||||
@cInclude("wlr/types/wlr_data_device.h");
|
||||
|
@ -21,6 +21,8 @@ pub const c = @cImport({
|
|||
@cInclude("wlr/types/wlr_xdg_shell.h");
|
||||
@cInclude("wlr/util/log.h");
|
||||
@cInclude("xkbcommon/xkbcommon.h");
|
||||
|
||||
@cInclude("include/render.h");
|
||||
});
|
||||
|
||||
pub const manual = struct {
|
||||
|
|
312
src/main.zig
312
src/main.zig
|
@ -11,8 +11,8 @@ const Server = struct {
|
|||
new_xdg_surface: c.wl_listener,
|
||||
views: c.wl_list,
|
||||
|
||||
cursor: ?*c.wlr_cursor,
|
||||
cursor_mgr: ?*c.wlr_xcursor_manager,
|
||||
cursor: *c.wlr_cursor,
|
||||
cursor_mgr: *c.wlr_xcursor_manager,
|
||||
cursor_motion: c.wl_listener,
|
||||
cursor_motion_absolute: c.wl_listener,
|
||||
cursor_button: c.wl_listener,
|
||||
|
@ -31,7 +31,7 @@ const Server = struct {
|
|||
grab_height: c_int,
|
||||
resize_edges: u32,
|
||||
|
||||
output_layout: ?*c.wlr_output_layout,
|
||||
output_layout: *c.wlr_output_layout,
|
||||
outputs: c.wl_list,
|
||||
new_output: c.wl_listener,
|
||||
};
|
||||
|
@ -337,7 +337,7 @@ fn server_new_xdg_surface(listener: [*c]c.wl_listener, data: ?*c_void) callconv(
|
|||
view.*.destroy.notify = xdg_surface_destroy;
|
||||
c.wl_signal_add(&xdg_surface.*.events.destroy, &view.*.destroy);
|
||||
|
||||
var toplevel = xdg_surface.*.unnamed_161.toplevel;
|
||||
var toplevel = xdg_surface.*.unnamed_160.toplevel;
|
||||
view.*.request_move.notify = xdg_toplevel_request_move;
|
||||
c.wl_signal_add(&toplevel.*.events.request_move, &view.*.request_move);
|
||||
|
||||
|
@ -360,7 +360,7 @@ fn keyboard_handle_modifiers(listener: [*c]c.wl_listener, data: ?*c_void) callco
|
|||
c.wlr_seat_set_keyboard(keyboard.*.server.*.seat, keyboard.*.device);
|
||||
|
||||
// Send modifiers to the client.
|
||||
c.wlr_seat_keyboard_notify_modifiers(keyboard.*.server.*.seat, &keyboard.*.device.*.unnamed_132.keyboard.*.modifiers);
|
||||
c.wlr_seat_keyboard_notify_modifiers(keyboard.*.server.*.seat, &keyboard.*.device.*.unnamed_37.keyboard.*.modifiers);
|
||||
}
|
||||
|
||||
fn handle_keybinding(server: *Server, sym: c.xkb_keysym_t) bool {
|
||||
|
@ -394,7 +394,7 @@ fn keyboard_handle_key(listener: [*c]c.wl_listener, data: ?*c_void) callconv(.C)
|
|||
|
||||
const server = keyboard.*.server;
|
||||
const seat = server.*.seat;
|
||||
const keyboard_device = keyboard.*.device.*.unnamed_132.keyboard;
|
||||
const keyboard_device = keyboard.*.device.*.unnamed_37.keyboard;
|
||||
|
||||
// Translate libinput keycode -> xkbcommon
|
||||
const keycode = event.*.keycode + 8;
|
||||
|
@ -444,7 +444,7 @@ fn server_new_keyboard(server: *Server, device: *c.wlr_input_device) void {
|
|||
const keymap = man_c.xkb_map_new_from_names(context, &rules, c.enum_xkb_keymap_compile_flags.XKB_KEYMAP_COMPILE_NO_FLAGS);
|
||||
defer c.xkb_keymap_unref(keymap);
|
||||
|
||||
var keyboard_device = device.*.unnamed_132.keyboard;
|
||||
var keyboard_device = device.*.unnamed_37.keyboard;
|
||||
c.wlr_keyboard_set_keymap(keyboard_device, keymap);
|
||||
c.wlr_keyboard_set_repeat_info(keyboard_device, 25, 600);
|
||||
|
||||
|
@ -460,6 +460,14 @@ fn server_new_keyboard(server: *Server, device: *c.wlr_input_device) void {
|
|||
c.wl_list_insert(&server.*.keyboards, &keyboard.*.link);
|
||||
}
|
||||
|
||||
fn server_new_pointer(server: *Server, device: *c.struct_wlr_input_device) void {
|
||||
// We don't do anything special with pointers. All of our pointer handling
|
||||
// is proxied through wlr_cursor. On another compositor, you might take this
|
||||
// opportunity to do libinput configuration on the device to set
|
||||
// acceleration, etc.
|
||||
c.wlr_cursor_attach_input_device(server.*.cursor, device);
|
||||
}
|
||||
|
||||
fn server_new_input(listener: [*c]c.wl_listener, data: ?*c_void) callconv(.C) void {
|
||||
// This event is raised by the backend when a new input device becomes available.
|
||||
var server = @fieldParentPtr(Server, "new_input", listener);
|
||||
|
@ -467,10 +475,14 @@ fn server_new_input(listener: [*c]c.wl_listener, data: ?*c_void) callconv(.C) vo
|
|||
|
||||
switch (device.*.type) {
|
||||
.WLR_INPUT_DEVICE_KEYBOARD => server_new_keyboard(server, device),
|
||||
.WLR_INPUT_DEVICE_POINTER => server_new_pointer(server, device),
|
||||
else => {},
|
||||
}
|
||||
|
||||
var caps: u32 = 0;
|
||||
// We need to let the wlr_seat know what our capabilities are, which is
|
||||
// communiciated to the client. In TinyWL we always have a cursor, even if
|
||||
// there are no pointer devices, so we always include that capability.
|
||||
var caps: u32 = @intCast(u32, c.WL_SEAT_CAPABILITY_POINTER);
|
||||
// if list not empty
|
||||
if (c.wl_list_empty(&server.*.keyboards) == 0) {
|
||||
caps |= @intCast(u32, c.WL_SEAT_CAPABILITY_KEYBOARD);
|
||||
|
@ -478,7 +490,230 @@ fn server_new_input(listener: [*c]c.wl_listener, data: ?*c_void) callconv(.C) vo
|
|||
c.wlr_seat_set_capabilities(server.*.seat, caps);
|
||||
}
|
||||
|
||||
fn seat_request_cursor(listener: [*c]c.wl_listener, data: ?*c_void) callconv(.C) void {
|
||||
// This event is rasied by the seat when a client provides a cursor image
|
||||
var server = @fieldParentPtr(Server, "request_cursor", listener);
|
||||
var event = @ptrCast(*c.wlr_seat_pointer_request_set_cursor_event, @alignCast(@alignOf(*c.wlr_seat_pointer_request_set_cursor_event), data));
|
||||
var focused_client = server.*.seat.*.pointer_state.focused_client;
|
||||
|
||||
// This can be sent by any client, so we check to make sure this one is
|
||||
// actually has pointer focus first.
|
||||
if (focused_client == event.*.seat_client) {
|
||||
// Once we've vetted the client, we can tell the cursor to use the
|
||||
// provided surface as the cursor image. It will set the hardware cursor
|
||||
// on the output that it's currently on and continue to do so as the
|
||||
// cursor moves between outputs.
|
||||
c.wlr_cursor_set_surface(server.*.cursor, event.*.surface, event.*.hotspot_x, event.*.hotspot_y);
|
||||
}
|
||||
}
|
||||
|
||||
fn view_at(view: *View, lx: f64, ly: f64, surface: *?*c.wlr_surface, sx: *f64, sy: *f64) bool {
|
||||
// XDG toplevels may have nested surfaces, such as popup windows for context
|
||||
// menus or tooltips. This function tests if any of those are underneath the
|
||||
// coordinates lx and ly (in output Layout Coordinates). If so, it sets the
|
||||
// surface pointer to that wlr_surface and the sx and sy coordinates to the
|
||||
// coordinates relative to that surface's top-left corner.
|
||||
var view_sx = lx - @intToFloat(f64, view.*.x);
|
||||
var view_sy = ly - @intToFloat(f64, view.*.y);
|
||||
|
||||
// This variable seems to have been unsued in TinyWL
|
||||
// struct wlr_surface_state *state = &view->xdg_surface->surface->current;
|
||||
|
||||
var _sx: f64 = undefined;
|
||||
var _sy: f64 = undefined;
|
||||
var _surface = c.wlr_xdg_surface_surface_at(view.*.xdg_surface, view_sx, view_sy, &_sx, &_sy);
|
||||
|
||||
if (_surface) |surface_at| {
|
||||
sx.* = _sx;
|
||||
sy.* = _sy;
|
||||
surface.* = surface_at;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
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) {
|
||||
if (view_at(view, lx, ly, surface, sx, sy)) {
|
||||
return view;
|
||||
}
|
||||
|
||||
view = @fieldParentPtr(View, "link", view.*.link.next);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
fn process_cursor_move(server: *Server, time: u32) void {
|
||||
// Move the grabbed view to the new position.
|
||||
server.*.grabbed_view.?.*.x = @floatToInt(c_int, server.*.cursor.*.x - server.*.grab_x);
|
||||
server.*.grabbed_view.?.*.y = @floatToInt(c_int, server.*.cursor.*.y - server.*.grab_y);
|
||||
}
|
||||
|
||||
fn process_cursor_resize(server: *Server, time: u32) void {
|
||||
// Resizing the grabbed view can be a little bit complicated, because we
|
||||
// could be resizing from any corner or edge. This not only resizes the view
|
||||
// on one or two axes, but can also move the view if you resize from the top
|
||||
// or left edges (or top-left corner).
|
||||
//
|
||||
// Note that I took some shortcuts here. In a more fleshed-out compositor,
|
||||
// you'd wait for the client to prepare a buffer at the new size, then
|
||||
// commit any movement that was prepared.
|
||||
var view = server.*.grabbed_view;
|
||||
|
||||
var dx: f64 = (server.*.cursor.*.x - server.*.grab_x);
|
||||
var dy: f64 = (server.*.cursor.*.y - server.*.grab_y);
|
||||
var x: f64 = @intToFloat(f64, view.?.*.x);
|
||||
var y: f64 = @intToFloat(f64, view.?.*.y);
|
||||
|
||||
var width = @intToFloat(f64, server.*.grab_width);
|
||||
var height = @intToFloat(f64, server.*.grab_height);
|
||||
if (server.*.resize_edges & @intCast(u32, c.WLR_EDGE_TOP) != 0) {
|
||||
y = server.*.grab_y + dy;
|
||||
height -= dy;
|
||||
if (height < 1) {
|
||||
y += height;
|
||||
}
|
||||
} else if (server.*.resize_edges & @intCast(u32, c.WLR_EDGE_BOTTOM) != 0) {
|
||||
height += dy;
|
||||
}
|
||||
if (server.*.resize_edges & @intCast(u32, c.WLR_EDGE_LEFT) != 0) {
|
||||
x = server.*.grab_x + dx;
|
||||
width -= dx;
|
||||
if (width < 1) {
|
||||
x += width;
|
||||
}
|
||||
} else if (server.*.resize_edges & @intCast(u32, c.WLR_EDGE_RIGHT) != 0) {
|
||||
width += dx;
|
||||
}
|
||||
view.?.*.x = @floatToInt(c_int, x);
|
||||
view.?.*.y = @floatToInt(c_int, y);
|
||||
_ = c.wlr_xdg_toplevel_set_size(view.?.*.xdg_surface, @floatToInt(u32, width), @floatToInt(u32, height));
|
||||
}
|
||||
|
||||
fn process_cursor_motion(server: *Server, time: u32) void {
|
||||
// If the mode is non-passthrough, delegate to those functions.
|
||||
if (server.*.cursor_mode == CursorMode.Move) {
|
||||
process_cursor_move(server, time);
|
||||
return;
|
||||
} else if (server.*.cursor_mode == CursorMode.Resize) {
|
||||
process_cursor_resize(server, time);
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise, find the view under the pointer and send the event along.
|
||||
var sx: f64 = undefined;
|
||||
var sy: f64 = undefined;
|
||||
var seat = server.*.seat;
|
||||
var opt_surface: ?*c.wlr_surface = null;
|
||||
var view = desktop_view_at(server, server.*.cursor.*.x, server.*.cursor.*.y, &opt_surface, &sx, &sy);
|
||||
|
||||
if (view == null) {
|
||||
// If there's no view under the cursor, set the cursor image to a
|
||||
// default. This is what makes the cursor image appear when you move it
|
||||
// around the screen, not over any views.
|
||||
c.wlr_xcursor_manager_set_cursor_image(server.*.cursor_mgr, "left_ptr", server.*.cursor);
|
||||
}
|
||||
|
||||
if (opt_surface) |surface| {
|
||||
const focus_changed = seat.*.pointer_state.focused_surface != surface;
|
||||
// "Enter" the surface if necessary. This lets the client know that the
|
||||
// cursor has entered one of its surfaces.
|
||||
//
|
||||
// Note that this gives the surface "pointer focus", which is distinct
|
||||
// from keyboard focus. You get pointer focus by moving the pointer over
|
||||
// a window.
|
||||
c.wlr_seat_pointer_notify_enter(seat, surface, sx, sy);
|
||||
if (!focus_changed) {
|
||||
// The enter event contains coordinates, so we only need to notify
|
||||
// on motion if the focus did not change.
|
||||
c.wlr_seat_pointer_notify_motion(seat, time, sx, sy);
|
||||
}
|
||||
} else {
|
||||
// Clear pointer focus so future button events and such are not sent to
|
||||
// the last client to have the cursor over it.
|
||||
c.wlr_seat_pointer_clear_focus(seat);
|
||||
}
|
||||
}
|
||||
|
||||
fn server_cursor_motion(listener: [*c]c.wl_listener, data: ?*c_void) callconv(.C) void {
|
||||
// This event is forwarded by the cursor when a pointer emits a _relative_
|
||||
// pointer motion event (i.e. a delta)
|
||||
var server = @fieldParentPtr(Server, "cursor_motion", listener);
|
||||
var event = @ptrCast(*c.wlr_event_pointer_motion, @alignCast(@alignOf(*c.wlr_event_pointer_motion), data));
|
||||
// The cursor doesn't move unless we tell it to. The cursor automatically
|
||||
// handles constraining the motion to the output layout, as well as any
|
||||
// special configuration applied for the specific input device which
|
||||
// generated the event. You can pass NULL for the device if you want to move
|
||||
// the cursor around without any input.
|
||||
c.wlr_cursor_move(server.*.cursor, event.*.device, event.*.delta_x, event.*.delta_y);
|
||||
process_cursor_motion(server, event.*.time_msec);
|
||||
}
|
||||
|
||||
fn server_cursor_motion_absolute(listener: [*c]c.wl_listener, data: ?*c_void) callconv(.C) void {
|
||||
// This event is forwarded by the cursor when a pointer emits an _absolute_
|
||||
// motion event, from 0..1 on each axis. This happens, for example, when
|
||||
// wlroots is running under a Wayland window rather than KMS+DRM, and you
|
||||
// move the mouse over the window. You could enter the window from any edge,
|
||||
// so we have to warp the mouse there. There is also some hardware which
|
||||
// emits these events.
|
||||
var server = @fieldParentPtr(Server, "cursor_motion_absolute", listener);
|
||||
var event = @ptrCast(*c.wlr_event_pointer_motion_absolute, @alignCast(@alignOf(*c.wlr_event_pointer_motion_absolute), data));
|
||||
c.wlr_cursor_warp_absolute(server.*.cursor, event.*.device, event.*.x, event.*.y);
|
||||
process_cursor_motion(server, event.*.time_msec);
|
||||
}
|
||||
|
||||
fn server_cursor_button(listener: [*c]c.wl_listener, data: ?*c_void) callconv(.C) void {
|
||||
// This event is forwarded by the cursor when a pointer emits a button
|
||||
// event.
|
||||
var server = @fieldParentPtr(Server, "cursor_button", listener);
|
||||
var event = @ptrCast(*c.wlr_event_pointer_button, @alignCast(@alignOf(*c.wlr_event_pointer_button), data));
|
||||
// Notify the client with pointer focus that a button press has occurred
|
||||
_ = c.wlr_seat_pointer_notify_button(server.*.seat, event.*.time_msec, event.*.button, event.*.state);
|
||||
|
||||
var sx: f64 = undefined;
|
||||
var sy: f64 = undefined;
|
||||
|
||||
var surface: ?*c.wlr_surface = null;
|
||||
var view = desktop_view_at(server, server.*.cursor.*.x, server.*.cursor.*.y, &surface, &sx, &sy);
|
||||
|
||||
if (event.*.state == c.enum_wlr_button_state.WLR_BUTTON_RELEASED) {
|
||||
// If you released any buttons, we exit interactive move/resize mode.
|
||||
server.*.cursor_mode = CursorMode.Passthrough;
|
||||
} else {
|
||||
// Focus that client if the button was _pressed_
|
||||
if (view) |v| {
|
||||
focus_view(v, surface.?);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn server_cursor_axis(listener: [*c]c.wl_listener, data: ?*c_void) callconv(.C) void {
|
||||
// This event is forwarded by the cursor when a pointer emits an axis event,
|
||||
// for example when you move the scroll wheel.
|
||||
var server = @fieldParentPtr(Server, "cursor_axis", listener);
|
||||
var event = @ptrCast(*c.wlr_event_pointer_axis, @alignCast(@alignOf(*c.wlr_event_pointer_axis), data));
|
||||
// Notify the client with pointer focus of the axis event.
|
||||
c.wlr_seat_pointer_notify_axis(server.*.seat, event.*.time_msec, event.*.orientation, event.*.delta, event.*.delta_discrete, event.*.source);
|
||||
}
|
||||
|
||||
fn server_cursor_frame(listener: [*c]c.wl_listener, data: ?*c_void) callconv(.C) void {
|
||||
// This event is forwarded by the cursor when a pointer emits an frame
|
||||
// event. Frame events are sent after regular pointer events to group
|
||||
// multiple events together. For instance, two axis events may happen at the
|
||||
// same time, in which case a frame event won't be sent in between.
|
||||
var server = @fieldParentPtr(Server, "cursor_frame", listener);
|
||||
// Notify the client with pointer focus of the frame event.
|
||||
c.wlr_seat_pointer_notify_frame(server.*.seat);
|
||||
}
|
||||
|
||||
const ZagError = error{
|
||||
InitError,
|
||||
CantAddSocket,
|
||||
CantStartBackend,
|
||||
CantSetEnv,
|
||||
|
@ -492,7 +727,7 @@ pub fn main() !void {
|
|||
var server: Server = undefined;
|
||||
// The Wayland display is managed by libwayland. It handles accepting
|
||||
// clients from the Unix socket, manging Wayland globals, and so on.
|
||||
server.wl_display = c.wl_display_create().?;
|
||||
server.wl_display = c.wl_display_create() orelse return ZagError.InitError;
|
||||
|
||||
// The backend is a wlroots feature which abstracts the underlying input and
|
||||
// output hardware. The autocreate option will choose the most suitable
|
||||
|
@ -502,12 +737,12 @@ pub fn main() !void {
|
|||
// backend uses the renderer, for example, to fall back to software cursors
|
||||
// if the backend does not support hardware cursors (some older GPUs
|
||||
// don't).
|
||||
server.backend = c.wlr_backend_autocreate(server.wl_display, null);
|
||||
server.backend = c.zag_wlr_backend_autocreate(server.wl_display) orelse return ZagError.InitError;
|
||||
|
||||
// If we don't provide a renderer, autocreate makes a GLES2 renderer for us.
|
||||
// The renderer is responsible for defining the various pixel formats it
|
||||
// supports for shared memory, this configures that for clients.
|
||||
server.renderer = c.wlr_backend_get_renderer(server.backend);
|
||||
server.renderer = c.zag_wlr_backend_get_renderer(server.backend);
|
||||
c.wlr_renderer_init_wl_display(server.renderer, server.wl_display);
|
||||
|
||||
// This creates some hands-off wlroots interfaces. The compositor is
|
||||
|
@ -535,6 +770,43 @@ pub fn main() !void {
|
|||
server.new_xdg_surface.notify = server_new_xdg_surface;
|
||||
c.wl_signal_add(&server.xdg_shell.*.events.new_surface, &server.new_xdg_surface);
|
||||
|
||||
// Creates a cursor, which is a wlroots utility for tracking the cursor
|
||||
// image shown on screen.
|
||||
server.cursor = c.wlr_cursor_create();
|
||||
c.wlr_cursor_attach_output_layout(server.cursor, server.output_layout);
|
||||
|
||||
// Creates an xcursor manager, another wlroots utility which loads up
|
||||
// Xcursor themes to source cursor images from and makes sure that cursor
|
||||
// images are available at all scale factors on the screen (necessary for
|
||||
// HiDPI support). We add a cursor theme at scale factor 1 to begin with.
|
||||
server.cursor_mgr = c.wlr_xcursor_manager_create(null, 24);
|
||||
_ = c.wlr_xcursor_manager_load(server.cursor_mgr, 1);
|
||||
|
||||
// wlr_cursor *only* displays an image on screen. It does not move around
|
||||
// when the pointer moves. However, we can attach input devices to it, and
|
||||
// it will generate aggregate events for all of them. In these events, we
|
||||
// can choose how we want to process them, forwarding them to clients and
|
||||
// moving the cursor around. More detail on this process is described in my
|
||||
// input handling blog post:
|
||||
//
|
||||
// https://drewdevault.com/2018/07/17/Input-handling-in-wlroots.html
|
||||
//
|
||||
// And more comments are sprinkled throughout the notify functions above.
|
||||
server.cursor_motion.notify = server_cursor_motion;
|
||||
c.wl_signal_add(&server.cursor.*.events.motion, &server.cursor_motion);
|
||||
|
||||
server.cursor_motion_absolute.notify = server_cursor_motion_absolute;
|
||||
c.wl_signal_add(&server.cursor.*.events.motion_absolute, &server.cursor_motion_absolute);
|
||||
|
||||
server.cursor_button.notify = server_cursor_button;
|
||||
c.wl_signal_add(&server.cursor.*.events.button, &server.cursor_button);
|
||||
|
||||
server.cursor_axis.notify = server_cursor_axis;
|
||||
c.wl_signal_add(&server.cursor.*.events.axis, &server.cursor_axis);
|
||||
|
||||
server.cursor_frame.notify = server_cursor_frame;
|
||||
c.wl_signal_add(&server.cursor.*.events.frame, &server.cursor_frame);
|
||||
|
||||
// Configures a seat, which is a single "seat" at which a user sits and
|
||||
// operates the computer. This conceptually includes up to one keyboard,
|
||||
// pointer, touch, and drawing tablet device. We also rig up a listener to
|
||||
|
@ -543,20 +815,20 @@ pub fn main() !void {
|
|||
server.new_input.notify = server_new_input;
|
||||
c.wl_signal_add(&server.backend.*.events.new_input, &server.new_input);
|
||||
server.seat = c.wlr_seat_create(server.wl_display, "seat0");
|
||||
// server.request_cursor.notify = seat_request_cursor;
|
||||
// c.wl_signal_add(&server.seat.*.events.request_set_cursor, &server.request_cursor);
|
||||
server.request_cursor.notify = seat_request_cursor;
|
||||
c.wl_signal_add(&server.seat.*.events.request_set_cursor, &server.request_cursor);
|
||||
|
||||
// Add a Unix socket to the Wayland display.
|
||||
const socket = c.wl_display_add_socket_auto(server.wl_display);
|
||||
if (socket == null) {
|
||||
c.wlr_backend_destroy(server.backend);
|
||||
c.zag_wlr_backend_destroy(server.backend);
|
||||
return ZagError.CantAddSocket;
|
||||
}
|
||||
|
||||
// Start the backend. This will enumerate outputs and inputs, become the DRM
|
||||
// master, etc
|
||||
if (!c.wlr_backend_start(server.backend)) {
|
||||
c.wlr_backend_destroy(server.backend);
|
||||
if (!c.zag_wlr_backend_start(server.backend)) {
|
||||
c.zag_wlr_backend_destroy(server.backend);
|
||||
c.wl_display_destroy(server.wl_display);
|
||||
return ZagError.CantStartBackend;
|
||||
}
|
||||
|
@ -567,15 +839,9 @@ pub fn main() !void {
|
|||
return ZagError.CantSetEnv;
|
||||
}
|
||||
|
||||
const argv = [_][]const u8{ "/bin/sh", "-c", "alacritty" };
|
||||
const argv = [_][]const u8{ "/bin/sh", "-c", "WAYLAND_DEBUG=1 alacritty" };
|
||||
var child = try std.ChildProcess.init(&argv, std.heap.c_allocator);
|
||||
try std.ChildProcess.spawn(child);
|
||||
//if (startup_cmd) {
|
||||
//if (std.os.linux.fork() == 0) {
|
||||
// execl("/bin/sh", "/bin/sh", "-c", startup_cmd, (void *)NULL);
|
||||
// std.os.linux.execve("/bin/sh",
|
||||
//}
|
||||
//}
|
||||
|
||||
// Run the Wayland event loop. This does not return until you exit the
|
||||
// compositor. Starting the backend rigged up all of the necessary event
|
||||
|
|
Loading…
Reference in a new issue