Get things compiling again
This commit is contained in:
parent
50494add40
commit
523d629fe0
10 changed files with 187 additions and 159 deletions
|
@ -2,14 +2,14 @@
|
||||||
#include <wlr/backend.h>
|
#include <wlr/backend.h>
|
||||||
#include <wlr/render/wlr_renderer.h>
|
#include <wlr/render/wlr_renderer.h>
|
||||||
|
|
||||||
struct wlr_backend *wlr_backend_autocreate(struct wl_display *display) {
|
struct wlr_backend *zag_wlr_backend_autocreate(struct wl_display *display) {
|
||||||
return wlr_backend_autocreate(display, NULL);
|
return wlr_backend_autocreate(display, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct wlr_renderer *wlr_backend_get_renderer(struct wlr_backend *backend) {
|
struct wlr_renderer *zag_wlr_backend_get_renderer(struct wlr_backend *backend) {
|
||||||
return wlr_backend_get_renderer(backend);
|
return wlr_backend_get_renderer(backend);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wlr_backend_start(struct wlr_backend *backend) {
|
bool zag_wlr_backend_start(struct wlr_backend *backend) {
|
||||||
return wlr_backend_start(backend);
|
return wlr_backend_start(backend);
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,9 +18,9 @@ struct wlr_backend {
|
||||||
} events;
|
} events;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct wlr_backend *wlr_backend_autocreate(struct wl_display *display);
|
struct wlr_backend *zag_wlr_backend_autocreate(struct wl_display *display);
|
||||||
struct wlr_renderer *wlr_backend_get_renderer(struct wlr_backend *backend);
|
struct wlr_renderer *zag_wlr_backend_get_renderer(struct wlr_backend *backend);
|
||||||
bool wlr_backend_start(struct wlr_backend *backend);
|
bool zag_wlr_backend_start(struct wlr_backend *backend);
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
10
src/c.zig
10
src/c.zig
|
@ -1,5 +1,3 @@
|
||||||
// Functions that couldn't be automatically translated
|
|
||||||
|
|
||||||
pub const c = @cImport({
|
pub const c = @cImport({
|
||||||
@cDefine("WLR_USE_UNSTABLE", {});
|
@cDefine("WLR_USE_UNSTABLE", {});
|
||||||
@cInclude("time.h");
|
@cInclude("time.h");
|
||||||
|
@ -22,11 +20,7 @@ pub const c = @cImport({
|
||||||
@cInclude("wlr/util/log.h");
|
@cInclude("wlr/util/log.h");
|
||||||
@cInclude("xkbcommon/xkbcommon.h");
|
@cInclude("xkbcommon/xkbcommon.h");
|
||||||
|
|
||||||
|
// Contains a subset of functions from wlr/backend.h and wlr/render/wlr_renderer.h
|
||||||
|
// that can be automatically imported
|
||||||
@cInclude("include/render.h");
|
@cInclude("include/render.h");
|
||||||
});
|
});
|
||||||
|
|
||||||
pub const manual = struct {
|
|
||||||
pub inline fn xkb_map_new_from_names(context: var, names: var, flags: var) ?*c.struct_xkb_keymap {
|
|
||||||
return c.xkb_keymap_new_from_names(context, names, flags);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
151
src/cursor.zig
151
src/cursor.zig
|
@ -1,6 +1,9 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const c = @import("c.zig").c;
|
const c = @import("c.zig").c;
|
||||||
|
|
||||||
|
const Seat = @import("seat.zig").Seat;
|
||||||
|
const View = @import("view.zig").View;
|
||||||
|
|
||||||
const CursorMode = enum {
|
const CursorMode = enum {
|
||||||
Passthrough,
|
Passthrough,
|
||||||
Move,
|
Move,
|
||||||
|
@ -19,9 +22,9 @@ pub const Cursor = struct {
|
||||||
listen_axis: c.wl_listener,
|
listen_axis: c.wl_listener,
|
||||||
listen_frame: c.wl_listener,
|
listen_frame: c.wl_listener,
|
||||||
|
|
||||||
listen_request_cursor: c.wl_listener,
|
listen_request_set_cursor: c.wl_listener,
|
||||||
|
|
||||||
cursor_mode: CursorMode,
|
mode: CursorMode,
|
||||||
grabbed_view: ?*View,
|
grabbed_view: ?*View,
|
||||||
grab_x: f64,
|
grab_x: f64,
|
||||||
grab_y: f64,
|
grab_y: f64,
|
||||||
|
@ -31,7 +34,6 @@ pub const Cursor = struct {
|
||||||
|
|
||||||
pub fn init(seat: *Seat) !@This() {
|
pub fn init(seat: *Seat) !@This() {
|
||||||
var cursor = @This(){
|
var cursor = @This(){
|
||||||
.server = seat.server,
|
|
||||||
.seat = seat,
|
.seat = seat,
|
||||||
|
|
||||||
// Creates a wlroots utility for tracking the cursor image shown on screen.
|
// Creates a wlroots utility for tracking the cursor image shown on screen.
|
||||||
|
@ -81,8 +83,8 @@ pub const Cursor = struct {
|
||||||
.resize_edges = 0,
|
.resize_edges = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
c.wlr_cursor_attach_output_layout(cursor.wlr_cursor, seat.*.server.*.output_layout);
|
c.wlr_cursor_attach_output_layout(cursor.wlr_cursor, seat.server.wlr_output_layout);
|
||||||
_ = c.wlr_xcursor_manager_load(server.cursor_mgr, 1);
|
_ = c.wlr_xcursor_manager_load(cursor.wlr_xcursor_manager, 1);
|
||||||
|
|
||||||
// wlr_cursor *only* displays an image on screen. It does not move around
|
// 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
|
// when the pointer moves. However, we can attach input devices to it, and
|
||||||
|
@ -97,18 +99,18 @@ pub const Cursor = struct {
|
||||||
c.wl_signal_add(&cursor.wlr_cursor.*.events.frame, &cursor.listen_frame);
|
c.wl_signal_add(&cursor.wlr_cursor.*.events.frame, &cursor.listen_frame);
|
||||||
|
|
||||||
// This listens for clients requesting a specific cursor image
|
// This listens for clients requesting a specific cursor image
|
||||||
c.wl_signal_add(&server.seat.*.events.request_set_cursor, &cursor.listen_request_set_cursor);
|
c.wl_signal_add(&seat.wlr_seat.events.request_set_cursor, &cursor.listen_request_set_cursor);
|
||||||
|
|
||||||
return cursor;
|
return cursor;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn process_cursor_move(server: *Server, time: u32) void {
|
fn process_move(self: *@This(), time: u32) void {
|
||||||
// Move the grabbed view to the new position.
|
// Move the grabbed view to the new position.
|
||||||
server.*.grabbed_view.?.*.x = @floatToInt(c_int, server.*.cursor.*.x - server.*.grab_x);
|
self.grabbed_view.?.*.x = @floatToInt(c_int, self.wlr_cursor.x - self.grab_x);
|
||||||
server.*.grabbed_view.?.*.y = @floatToInt(c_int, server.*.cursor.*.y - server.*.grab_y);
|
self.grabbed_view.?.*.y = @floatToInt(c_int, self.wlr_cursor.y - self.grab_y);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn process_cursor_resize(server: *Server, time: u32) void {
|
fn process_resize(self: *@This(), time: u32) void {
|
||||||
// Resizing the grabbed view can be a little bit complicated, because we
|
// 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
|
// 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
|
// on one or two axes, but can also move the view if you resize from the top
|
||||||
|
@ -117,61 +119,61 @@ pub const Cursor = struct {
|
||||||
// Note that I took some shortcuts here. In a more fleshed-out compositor,
|
// 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
|
// you'd wait for the client to prepare a buffer at the new size, then
|
||||||
// commit any movement that was prepared.
|
// commit any movement that was prepared.
|
||||||
var view = server.*.grabbed_view;
|
|
||||||
|
|
||||||
var dx: f64 = (server.*.cursor.*.x - server.*.grab_x);
|
// TODO: Handle null view
|
||||||
var dy: f64 = (server.*.cursor.*.y - server.*.grab_y);
|
var view = self.grabbed_view;
|
||||||
var x: f64 = @intToFloat(f64, view.?.*.x);
|
|
||||||
var y: f64 = @intToFloat(f64, view.?.*.y);
|
|
||||||
|
|
||||||
var width = @intToFloat(f64, server.*.grab_width);
|
var dx: f64 = self.wlr_cursor.x - self.grab_x;
|
||||||
var height = @intToFloat(f64, server.*.grab_height);
|
var dy: f64 = self.wlr_cursor.y - self.grab_y;
|
||||||
if (server.*.resize_edges & @intCast(u32, c.WLR_EDGE_TOP) != 0) {
|
var x: f64 = @intToFloat(f64, view.?.x);
|
||||||
y = server.*.grab_y + dy;
|
var y: f64 = @intToFloat(f64, view.?.y);
|
||||||
|
|
||||||
|
var width = @intToFloat(f64, self.grab_width);
|
||||||
|
var height = @intToFloat(f64, self.grab_height);
|
||||||
|
if (self.resize_edges & @intCast(u32, c.WLR_EDGE_TOP) != 0) {
|
||||||
|
y = self.grab_y + dy;
|
||||||
height -= dy;
|
height -= dy;
|
||||||
if (height < 1) {
|
if (height < 1) {
|
||||||
y += height;
|
y += height;
|
||||||
}
|
}
|
||||||
} else if (server.*.resize_edges & @intCast(u32, c.WLR_EDGE_BOTTOM) != 0) {
|
} else if (self.resize_edges & @intCast(u32, c.WLR_EDGE_BOTTOM) != 0) {
|
||||||
height += dy;
|
height += dy;
|
||||||
}
|
}
|
||||||
if (server.*.resize_edges & @intCast(u32, c.WLR_EDGE_LEFT) != 0) {
|
if (self.resize_edges & @intCast(u32, c.WLR_EDGE_LEFT) != 0) {
|
||||||
x = server.*.grab_x + dx;
|
x = self.grab_x + dx;
|
||||||
width -= dx;
|
width -= dx;
|
||||||
if (width < 1) {
|
if (width < 1) {
|
||||||
x += width;
|
x += width;
|
||||||
}
|
}
|
||||||
} else if (server.*.resize_edges & @intCast(u32, c.WLR_EDGE_RIGHT) != 0) {
|
} else if (self.resize_edges & @intCast(u32, c.WLR_EDGE_RIGHT) != 0) {
|
||||||
width += dx;
|
width += dx;
|
||||||
}
|
}
|
||||||
view.?.*.x = @floatToInt(c_int, x);
|
view.?.x = @floatToInt(c_int, x);
|
||||||
view.?.*.y = @floatToInt(c_int, y);
|
view.?.y = @floatToInt(c_int, y);
|
||||||
_ = c.wlr_xdg_toplevel_set_size(
|
_ = c.wlr_xdg_toplevel_set_size(
|
||||||
view.?.*.xdg_surface,
|
view.?.wlr_xdg_surface,
|
||||||
@floatToInt(u32, width),
|
@floatToInt(u32, width),
|
||||||
@floatToInt(u32, height),
|
@floatToInt(u32, height),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn process_cursor_motion(server: *Server, time: u32) void {
|
fn process_motion(self: *@This(), time: u32) void {
|
||||||
// If the mode is non-passthrough, delegate to those functions.
|
// If the mode is non-passthrough, delegate to those functions.
|
||||||
if (server.*.cursor_mode == CursorMode.Move) {
|
if (self.mode == CursorMode.Move) {
|
||||||
process_cursor_move(server, time);
|
self.process_move(time);
|
||||||
return;
|
return;
|
||||||
} else if (server.*.cursor_mode == CursorMode.Resize) {
|
} else if (self.mode == CursorMode.Resize) {
|
||||||
process_cursor_resize(server, time);
|
self.process_resize(time);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise, find the view under the pointer and send the event along.
|
// Otherwise, find the view under the pointer and send the event along.
|
||||||
var sx: f64 = undefined;
|
var sx: f64 = undefined;
|
||||||
var sy: f64 = undefined;
|
var sy: f64 = undefined;
|
||||||
var seat = server.*.seat;
|
|
||||||
var opt_surface: ?*c.wlr_surface = null;
|
var opt_surface: ?*c.wlr_surface = null;
|
||||||
var view = desktop_view_at(
|
var view = self.seat.server.desktop_view_at(
|
||||||
server,
|
self.wlr_cursor.x,
|
||||||
server.*.cursor.*.x,
|
self.wlr_cursor.y,
|
||||||
server.*.cursor.*.y,
|
|
||||||
&opt_surface,
|
&opt_surface,
|
||||||
&sx,
|
&sx,
|
||||||
&sy,
|
&sy,
|
||||||
|
@ -182,37 +184,38 @@ pub const Cursor = struct {
|
||||||
// default. This is what makes the cursor image appear when you move it
|
// default. This is what makes the cursor image appear when you move it
|
||||||
// around the screen, not over any views.
|
// around the screen, not over any views.
|
||||||
c.wlr_xcursor_manager_set_cursor_image(
|
c.wlr_xcursor_manager_set_cursor_image(
|
||||||
server.*.cursor_mgr,
|
self.wlr_xcursor_manager,
|
||||||
"left_ptr",
|
"left_ptr",
|
||||||
server.*.cursor,
|
self.wlr_cursor,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var wlr_seat = self.seat.wlr_seat;
|
||||||
if (opt_surface) |surface| {
|
if (opt_surface) |surface| {
|
||||||
const focus_changed = seat.*.pointer_state.focused_surface != surface;
|
const focus_changed = wlr_seat.pointer_state.focused_surface != surface;
|
||||||
// "Enter" the surface if necessary. This lets the client know that the
|
// "Enter" the surface if necessary. This lets the client know that the
|
||||||
// cursor has entered one of its surfaces.
|
// cursor has entered one of its surfaces.
|
||||||
//
|
//
|
||||||
// Note that this gives the surface "pointer focus", which is distinct
|
// Note that this gives the surface "pointer focus", which is distinct
|
||||||
// from keyboard focus. You get pointer focus by moving the pointer over
|
// from keyboard focus. You get pointer focus by moving the pointer over
|
||||||
// a window.
|
// a window.
|
||||||
c.wlr_seat_pointer_notify_enter(seat, surface, sx, sy);
|
c.wlr_seat_pointer_notify_enter(wlr_seat, surface, sx, sy);
|
||||||
if (!focus_changed) {
|
if (!focus_changed) {
|
||||||
// The enter event contains coordinates, so we only need to notify
|
// The enter event contains coordinates, so we only need to notify
|
||||||
// on motion if the focus did not change.
|
// on motion if the focus did not change.
|
||||||
c.wlr_seat_pointer_notify_motion(seat, time, sx, sy);
|
c.wlr_seat_pointer_notify_motion(wlr_seat, time, sx, sy);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Clear pointer focus so future button events and such are not sent to
|
// Clear pointer focus so future button events and such are not sent to
|
||||||
// the last client to have the cursor over it.
|
// the last client to have the cursor over it.
|
||||||
c.wlr_seat_pointer_clear_focus(seat);
|
c.wlr_seat_pointer_clear_focus(wlr_seat);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_motion(listener: [*c]c.wl_listener, data: ?*c_void) callconv(.C) void {
|
fn handle_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_
|
// This event is forwarded by the cursor when a pointer emits a _relative_
|
||||||
// pointer motion event (i.e. a delta)
|
// pointer motion event (i.e. a delta)
|
||||||
var server = @fieldParentPtr(Server, "cursor_motion", listener);
|
var cursor = @fieldParentPtr(Cursor, "listen_motion", listener);
|
||||||
var event = @ptrCast(
|
var event = @ptrCast(
|
||||||
*c.wlr_event_pointer_motion,
|
*c.wlr_event_pointer_motion,
|
||||||
@alignCast(@alignOf(*c.wlr_event_pointer_motion), data),
|
@alignCast(@alignOf(*c.wlr_event_pointer_motion), data),
|
||||||
|
@ -222,8 +225,8 @@ pub const Cursor = struct {
|
||||||
// special configuration applied for the specific input device which
|
// special configuration applied for the specific input device which
|
||||||
// generated the event. You can pass NULL for the device if you want to move
|
// generated the event. You can pass NULL for the device if you want to move
|
||||||
// the cursor around without any input.
|
// the cursor around without any input.
|
||||||
c.wlr_cursor_move(server.*.cursor, event.*.device, event.*.delta_x, event.*.delta_y);
|
c.wlr_cursor_move(cursor.wlr_cursor, event.device, event.delta_x, event.delta_y);
|
||||||
process_cursor_motion(server, event.*.time_msec);
|
cursor.process_motion(event.time_msec);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_motion_absolute(listener: [*c]c.wl_listener, data: ?*c_void) callconv(.C) void {
|
fn handle_motion_absolute(listener: [*c]c.wl_listener, data: ?*c_void) callconv(.C) void {
|
||||||
|
@ -233,39 +236,38 @@ pub const Cursor = struct {
|
||||||
// move the mouse over the window. You could enter the window from any edge,
|
// 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
|
// so we have to warp the mouse there. There is also some hardware which
|
||||||
// emits these events.
|
// emits these events.
|
||||||
var server = @fieldParentPtr(Server, "cursor_motion_absolute", listener);
|
var cursor = @fieldParentPtr(Cursor, "listen_motion_absolute", listener);
|
||||||
var event = @ptrCast(
|
var event = @ptrCast(
|
||||||
*c.wlr_event_pointer_motion_absolute,
|
*c.wlr_event_pointer_motion_absolute,
|
||||||
@alignCast(@alignOf(*c.wlr_event_pointer_motion_absolute), data),
|
@alignCast(@alignOf(*c.wlr_event_pointer_motion_absolute), data),
|
||||||
);
|
);
|
||||||
c.wlr_cursor_warp_absolute(server.*.cursor, event.*.device, event.*.x, event.*.y);
|
c.wlr_cursor_warp_absolute(cursor.wlr_cursor, event.device, event.x, event.y);
|
||||||
process_cursor_motion(server, event.*.time_msec);
|
cursor.process_motion(event.time_msec);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_button(listener: [*c]c.wl_listener, data: ?*c_void) callconv(.C) void {
|
fn handle_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
|
// This event is forwarded by the cursor when a pointer emits a button
|
||||||
// event.
|
// event.
|
||||||
var server = @fieldParentPtr(Server, "cursor_button", listener);
|
var cursor = @fieldParentPtr(Cursor, "listen_button", listener);
|
||||||
var event = @ptrCast(
|
var event = @ptrCast(
|
||||||
*c.wlr_event_pointer_button,
|
*c.wlr_event_pointer_button,
|
||||||
@alignCast(@alignOf(*c.wlr_event_pointer_button), data),
|
@alignCast(@alignOf(*c.wlr_event_pointer_button), data),
|
||||||
);
|
);
|
||||||
// Notify the client with pointer focus that a button press has occurred
|
// Notify the client with pointer focus that a button press has occurred
|
||||||
_ = c.wlr_seat_pointer_notify_button(
|
_ = c.wlr_seat_pointer_notify_button(
|
||||||
server.*.seat,
|
cursor.seat.wlr_seat,
|
||||||
event.*.time_msec,
|
event.time_msec,
|
||||||
event.*.button,
|
event.button,
|
||||||
event.*.state,
|
event.state,
|
||||||
);
|
);
|
||||||
|
|
||||||
var sx: f64 = undefined;
|
var sx: f64 = undefined;
|
||||||
var sy: f64 = undefined;
|
var sy: f64 = undefined;
|
||||||
|
|
||||||
var surface: ?*c.wlr_surface = null;
|
var surface: ?*c.wlr_surface = null;
|
||||||
var view = desktop_view_at(
|
var view = cursor.seat.server.desktop_view_at(
|
||||||
server,
|
cursor.wlr_cursor.x,
|
||||||
server.*.cursor.*.x,
|
cursor.wlr_cursor.y,
|
||||||
server.*.cursor.*.y,
|
|
||||||
&surface,
|
&surface,
|
||||||
&sx,
|
&sx,
|
||||||
&sy,
|
&sy,
|
||||||
|
@ -273,11 +275,11 @@ pub const Cursor = struct {
|
||||||
|
|
||||||
if (event.*.state == c.enum_wlr_button_state.WLR_BUTTON_RELEASED) {
|
if (event.*.state == c.enum_wlr_button_state.WLR_BUTTON_RELEASED) {
|
||||||
// If you released any buttons, we exit interactive move/resize mode.
|
// If you released any buttons, we exit interactive move/resize mode.
|
||||||
server.*.cursor_mode = CursorMode.Passthrough;
|
cursor.mode = CursorMode.Passthrough;
|
||||||
} else {
|
} else {
|
||||||
// Focus that client if the button was _pressed_
|
// Focus that client if the button was _pressed_
|
||||||
if (view) |v| {
|
if (view) |v| {
|
||||||
focus_view(v, surface.?);
|
v.focus(surface.?);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -285,19 +287,20 @@ pub const Cursor = struct {
|
||||||
fn handle_axis(listener: [*c]c.wl_listener, data: ?*c_void) callconv(.C) void {
|
fn handle_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,
|
// This event is forwarded by the cursor when a pointer emits an axis event,
|
||||||
// for example when you move the scroll wheel.
|
// for example when you move the scroll wheel.
|
||||||
var server = @fieldParentPtr(Server, "cursor_axis", listener);
|
var cursor = @fieldParentPtr(Cursor, "listen_axis", listener);
|
||||||
var event = @ptrCast(
|
var event = @ptrCast(
|
||||||
*c.wlr_event_pointer_axis,
|
*c.wlr_event_pointer_axis,
|
||||||
@alignCast(@alignOf(*c.wlr_event_pointer_axis), data),
|
@alignCast(@alignOf(*c.wlr_event_pointer_axis), data),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Notify the client with pointer focus of the axis event.
|
// Notify the client with pointer focus of the axis event.
|
||||||
c.wlr_seat_pointer_notify_axis(
|
c.wlr_seat_pointer_notify_axis(
|
||||||
server.*.seat,
|
cursor.seat.wlr_seat,
|
||||||
event.*.time_msec,
|
event.time_msec,
|
||||||
event.*.orientation,
|
event.orientation,
|
||||||
event.*.delta,
|
event.delta,
|
||||||
event.*.delta_discrete,
|
event.delta_discrete,
|
||||||
event.*.source,
|
event.source,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -306,19 +309,19 @@ pub const Cursor = struct {
|
||||||
// event. Frame events are sent after regular pointer events to group
|
// event. Frame events are sent after regular pointer events to group
|
||||||
// multiple events together. For instance, two axis events may happen at the
|
// 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.
|
// same time, in which case a frame event won't be sent in between.
|
||||||
var server = @fieldParentPtr(Server, "cursor_frame", listener);
|
var cursor = @fieldParentPtr(Cursor, "listen_frame", listener);
|
||||||
// Notify the client with pointer focus of the frame event.
|
// Notify the client with pointer focus of the frame event.
|
||||||
c.wlr_seat_pointer_notify_frame(server.*.seat);
|
c.wlr_seat_pointer_notify_frame(cursor.seat.wlr_seat);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_request_set_cursor(listener: [*c]c.wl_listener, data: ?*c_void) callconv(.C) void {
|
fn handle_request_set_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
|
// This event is rasied by the seat when a client provides a cursor image
|
||||||
var server = @fieldParentPtr(Server, "request_cursor", listener);
|
var cursor = @fieldParentPtr(Cursor, "listen_request_set_cursor", listener);
|
||||||
var event = @ptrCast(
|
var event = @ptrCast(
|
||||||
*c.wlr_seat_pointer_request_set_cursor_event,
|
*c.wlr_seat_pointer_request_set_cursor_event,
|
||||||
@alignCast(@alignOf(*c.wlr_seat_pointer_request_set_cursor_event), data),
|
@alignCast(@alignOf(*c.wlr_seat_pointer_request_set_cursor_event), data),
|
||||||
);
|
);
|
||||||
var focused_client = server.*.seat.*.pointer_state.focused_client;
|
const focused_client = cursor.seat.wlr_seat.pointer_state.focused_client;
|
||||||
|
|
||||||
// This can be sent by any client, so we check to make sure this one is
|
// This can be sent by any client, so we check to make sure this one is
|
||||||
// actually has pointer focus first.
|
// actually has pointer focus first.
|
||||||
|
@ -328,10 +331,10 @@ pub const Cursor = struct {
|
||||||
// on the output that it's currently on and continue to do so as the
|
// on the output that it's currently on and continue to do so as the
|
||||||
// cursor moves between outputs.
|
// cursor moves between outputs.
|
||||||
c.wlr_cursor_set_surface(
|
c.wlr_cursor_set_surface(
|
||||||
server.*.cursor,
|
cursor.wlr_cursor,
|
||||||
event.*.surface,
|
event.surface,
|
||||||
event.*.hotspot_x,
|
event.hotspot_x,
|
||||||
event.*.hotspot_y,
|
event.hotspot_y,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const c = @import("c.zig").c;
|
const c = @import("c.zig").c;
|
||||||
|
|
||||||
const Keyboard = struct {
|
const Seat = @import("seat.zig").Seat;
|
||||||
|
|
||||||
|
pub const Keyboard = struct {
|
||||||
seat: *Seat,
|
seat: *Seat,
|
||||||
device: *c.wlr_input_device,
|
device: *c.wlr_input_device,
|
||||||
|
|
||||||
|
@ -35,7 +37,7 @@ const Keyboard = struct {
|
||||||
const context = c.xkb_context_new(c.enum_xkb_context_flags.XKB_CONTEXT_NO_FLAGS);
|
const context = c.xkb_context_new(c.enum_xkb_context_flags.XKB_CONTEXT_NO_FLAGS);
|
||||||
defer c.xkb_context_unref(context);
|
defer c.xkb_context_unref(context);
|
||||||
|
|
||||||
const keymap = man_c.xkb_map_new_from_names(
|
const keymap = c.xkb_keymap_new_from_names(
|
||||||
context,
|
context,
|
||||||
&rules,
|
&rules,
|
||||||
c.enum_xkb_keymap_compile_flags.XKB_KEYMAP_COMPILE_NO_FLAGS,
|
c.enum_xkb_keymap_compile_flags.XKB_KEYMAP_COMPILE_NO_FLAGS,
|
||||||
|
@ -47,8 +49,8 @@ const Keyboard = struct {
|
||||||
c.wlr_keyboard_set_repeat_info(keyboard_device, 25, 600);
|
c.wlr_keyboard_set_repeat_info(keyboard_device, 25, 600);
|
||||||
|
|
||||||
// Setup listeners for keyboard events
|
// Setup listeners for keyboard events
|
||||||
c.wl_signal_add(&keyboard_device.*.events.modifiers, &keyboard.*.listen_modifiers);
|
c.wl_signal_add(&keyboard_device.*.events.modifiers, &keyboard.listen_modifiers);
|
||||||
c.wl_signal_add(&keyboard_device.*.events.key, &keyboard.*.listen_key);
|
c.wl_signal_add(&keyboard_device.*.events.key, &keyboard.listen_key);
|
||||||
|
|
||||||
return keyboard;
|
return keyboard;
|
||||||
}
|
}
|
||||||
|
@ -62,10 +64,10 @@ const Keyboard = struct {
|
||||||
// Wayland protocol - not wlroots. We assign all connected keyboards to the
|
// Wayland protocol - not wlroots. We assign all connected keyboards to the
|
||||||
// same seat. You can swap out the underlying wlr_keyboard like this and
|
// same seat. You can swap out the underlying wlr_keyboard like this and
|
||||||
// wlr_seat handles this transparently.
|
// wlr_seat handles this transparently.
|
||||||
c.wlr_seat_set_keyboard(keyboard.*.server.*.seat, keyboard.*.device);
|
c.wlr_seat_set_keyboard(keyboard.seat.wlr_seat, keyboard.*.device);
|
||||||
|
|
||||||
// Send modifiers to the client.
|
// Send modifiers to the client.
|
||||||
c.wlr_seat_keyboard_notify_modifiers(keyboard.*.server.*.seat, &keyboard.*.device.*.unnamed_37.keyboard.*.modifiers);
|
c.wlr_seat_keyboard_notify_modifiers(keyboard.seat.wlr_seat, &keyboard.*.device.*.unnamed_37.keyboard.*.modifiers);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_key(listener: [*c]c.wl_listener, data: ?*c_void) callconv(.C) void {
|
fn handle_key(listener: [*c]c.wl_listener, data: ?*c_void) callconv(.C) void {
|
||||||
|
@ -76,26 +78,24 @@ const Keyboard = struct {
|
||||||
@alignCast(@alignOf(*c.wlr_event_keyboard_key), data),
|
@alignCast(@alignOf(*c.wlr_event_keyboard_key), data),
|
||||||
);
|
);
|
||||||
|
|
||||||
const server = keyboard.*.server;
|
const keyboard_device = keyboard.device.unnamed_37.keyboard;
|
||||||
const seat = server.*.seat;
|
|
||||||
const keyboard_device = keyboard.*.device.*.unnamed_37.keyboard;
|
|
||||||
|
|
||||||
// Translate libinput keycode -> xkbcommon
|
// Translate libinput keycode -> xkbcommon
|
||||||
const keycode = event.*.keycode + 8;
|
const keycode = event.keycode + 8;
|
||||||
// Get a list of keysyms based on the keymap for this keyboard
|
// Get a list of keysyms based on the keymap for this keyboard
|
||||||
var syms: *c.xkb_keysym_t = undefined;
|
var syms: ?[*]c.xkb_keysym_t = undefined;
|
||||||
const nsyms = c.xkb_state_key_get_syms(keyboard_device.*.xkb_state, keycode, &syms);
|
const nsyms = c.xkb_state_key_get_syms(keyboard_device.*.xkb_state, keycode, &syms);
|
||||||
|
|
||||||
var handled = false;
|
var handled = false;
|
||||||
const modifiers = c.wlr_keyboard_get_modifiers(keyboard_device);
|
const modifiers = c.wlr_keyboard_get_modifiers(keyboard_device);
|
||||||
if (modifiers & @intCast(u32, c.WLR_MODIFIER_LOGO) != 0 and
|
if (modifiers & @intCast(u32, c.WLR_MODIFIER_LOGO) != 0 and
|
||||||
event.*.state == c.enum_wlr_key_state.WLR_KEY_PRESSED)
|
event.state == c.enum_wlr_key_state.WLR_KEY_PRESSED)
|
||||||
{
|
{
|
||||||
// If mod is held down and this button was _pressed_, we attempt to
|
// If mod is held down and this button was _pressed_, we attempt to
|
||||||
// process it as a compositor keybinding.
|
// process it as a compositor keybinding.
|
||||||
var i: usize = 0;
|
var i: usize = 0;
|
||||||
while (i < nsyms) {
|
while (i < nsyms) {
|
||||||
handled = keyboard.seat.server.handle_keybinding(syms[i]);
|
handled = keyboard.seat.server.handle_keybinding(syms.?[i]);
|
||||||
if (handled) {
|
if (handled) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -105,12 +105,13 @@ const Keyboard = struct {
|
||||||
|
|
||||||
if (!handled) {
|
if (!handled) {
|
||||||
// Otherwise, we pass it along to the client.
|
// Otherwise, we pass it along to the client.
|
||||||
c.wlr_seat_set_keyboard(seat, keyboard.*.device);
|
const wlr_seat = keyboard.seat.wlr_seat;
|
||||||
|
c.wlr_seat_set_keyboard(wlr_seat, keyboard.device);
|
||||||
c.wlr_seat_keyboard_notify_key(
|
c.wlr_seat_keyboard_notify_key(
|
||||||
seat,
|
wlr_seat,
|
||||||
event.*.time_msec,
|
event.time_msec,
|
||||||
event.*.keycode,
|
event.keycode,
|
||||||
@intCast(u32, @enumToInt(event.*.state)),
|
@intCast(u32, @enumToInt(event.state)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const c = @import("c.zig").c;
|
const c = @import("c.zig").c;
|
||||||
|
|
||||||
|
const Server = @import("server.zig").Server;
|
||||||
|
|
||||||
pub fn main() !void {
|
pub fn main() !void {
|
||||||
std.debug.warn("Starting up.\n", .{});
|
std.debug.warn("Starting up.\n", .{});
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const c = @import("c.zig").c;
|
const c = @import("c.zig").c;
|
||||||
|
|
||||||
|
const Server = @import("server.zig").Server;
|
||||||
|
const View = @import("view.zig").View;
|
||||||
|
|
||||||
const RenderData = struct {
|
const RenderData = struct {
|
||||||
output: *c.wlr_output,
|
output: *c.wlr_output,
|
||||||
renderer: *c.wlr_renderer,
|
renderer: *c.wlr_renderer,
|
||||||
|
@ -8,7 +11,7 @@ const RenderData = struct {
|
||||||
when: *c.struct_timespec,
|
when: *c.struct_timespec,
|
||||||
};
|
};
|
||||||
|
|
||||||
const Output = struct {
|
pub const Output = struct {
|
||||||
server: *Server,
|
server: *Server,
|
||||||
wlr_output: *c.wlr_output,
|
wlr_output: *c.wlr_output,
|
||||||
listen_frame: c.wl_listener,
|
listen_frame: c.wl_listener,
|
||||||
|
@ -40,13 +43,13 @@ const Output = struct {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Sets up a listener for the frame notify event.
|
// Sets up a listener for the frame notify event.
|
||||||
c.wl_signal_add(&wlr_output.*.events.frame, &output.*.listen_frame);
|
c.wl_signal_add(&wlr_output.events.frame, &output.listen_frame);
|
||||||
|
|
||||||
// Add the new output to the layout. The add_auto function arranges outputs
|
// Add the new output to the layout. The add_auto function arranges outputs
|
||||||
// from left-to-right in the order they appear. A more sophisticated
|
// from left-to-right in the order they appear. A more sophisticated
|
||||||
// compositor would let the user configure the arrangement of outputs in the
|
// compositor would let the user configure the arrangement of outputs in the
|
||||||
// layout.
|
// layout.
|
||||||
c.wlr_output_layout_add_auto(server.output_layout, wlr_output);
|
c.wlr_output_layout_add_auto(server.wlr_output_layout, wlr_output);
|
||||||
|
|
||||||
// Creating the global adds a wl_output global to the display, which Wayland
|
// Creating the global adds a wl_output global to the display, which Wayland
|
||||||
// clients can see to find out information about the output (such as
|
// clients can see to find out information about the output (such as
|
||||||
|
@ -59,8 +62,8 @@ const Output = struct {
|
||||||
fn handle_frame(listener: [*c]c.wl_listener, data: ?*c_void) callconv(.C) void {
|
fn handle_frame(listener: [*c]c.wl_listener, data: ?*c_void) callconv(.C) void {
|
||||||
// This function is called every time an output is ready to display a frame,
|
// This function is called every time an output is ready to display a frame,
|
||||||
// generally at the output's refresh rate (e.g. 60Hz).
|
// generally at the output's refresh rate (e.g. 60Hz).
|
||||||
var output = @fieldParentPtr(Output, "frame", listener);
|
var output = @fieldParentPtr(Output, "listen_frame", listener);
|
||||||
var renderer = output.*.server.*.renderer;
|
var renderer = output.server.wlr_renderer;
|
||||||
|
|
||||||
var now: c.struct_timespec = undefined;
|
var now: c.struct_timespec = undefined;
|
||||||
_ = c.clock_gettime(c.CLOCK_MONOTONIC, &now);
|
_ = c.clock_gettime(c.CLOCK_MONOTONIC, &now);
|
||||||
|
@ -93,7 +96,7 @@ const Output = struct {
|
||||||
};
|
};
|
||||||
// This calls our render_surface function for each surface among the
|
// This calls our render_surface function for each surface among the
|
||||||
// xdg_surface's toplevel and popups.
|
// xdg_surface's toplevel and popups.
|
||||||
c.wlr_xdg_surface_for_each_surface(view.*.xdg_surface, render_surface, &rdata);
|
c.wlr_xdg_surface_for_each_surface(view.*.wlr_xdg_surface, render_surface, &rdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hardware cursors are rendered by the GPU on a separate plane, and can be
|
// Hardware cursors are rendered by the GPU on a separate plane, and can be
|
||||||
|
@ -133,7 +136,7 @@ const Output = struct {
|
||||||
// output-local coordinates, or (2000 - 1920).
|
// output-local coordinates, or (2000 - 1920).
|
||||||
var ox: f64 = 0.0;
|
var ox: f64 = 0.0;
|
||||||
var oy: f64 = 0.0;
|
var oy: f64 = 0.0;
|
||||||
c.wlr_output_layout_output_coords(view.*.server.*.output_layout, output, &ox, &oy);
|
c.wlr_output_layout_output_coords(view.server.wlr_output_layout, output, &ox, &oy);
|
||||||
ox += @intToFloat(f64, view.*.x + sx);
|
ox += @intToFloat(f64, view.*.x + sx);
|
||||||
oy += @intToFloat(f64, view.*.y + sy);
|
oy += @intToFloat(f64, view.*.y + sy);
|
||||||
|
|
||||||
|
|
24
src/seat.zig
24
src/seat.zig
|
@ -1,6 +1,10 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const c = @import("c.zig").c;
|
const c = @import("c.zig").c;
|
||||||
|
|
||||||
|
const Cursor = @import("cursor.zig").Cursor;
|
||||||
|
const Keyboard = @import("keyboard.zig").Keyboard;
|
||||||
|
const Server = @import("server.zig").Server;
|
||||||
|
|
||||||
// TODO: InputManager and multi-seat support
|
// TODO: InputManager and multi-seat support
|
||||||
pub const Seat = struct {
|
pub const Seat = struct {
|
||||||
server: *Server,
|
server: *Server,
|
||||||
|
@ -13,7 +17,7 @@ pub const Seat = struct {
|
||||||
// Mulitple keyboards are handled separately
|
// Mulitple keyboards are handled separately
|
||||||
keyboards: std.ArrayList(Keyboard),
|
keyboards: std.ArrayList(Keyboard),
|
||||||
|
|
||||||
pub fn init(server: *Server, allocator: *std.mem.Allocator) @This() {
|
pub fn init(server: *Server, allocator: *std.mem.Allocator) !@This() {
|
||||||
var seat = @This(){
|
var seat = @This(){
|
||||||
.server = server,
|
.server = server,
|
||||||
// This seems to be the default seat name used by compositors
|
// This seems to be the default seat name used by compositors
|
||||||
|
@ -27,16 +31,18 @@ pub const Seat = struct {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
seat.cursor = cursor.Cursor.init(server);
|
seat.cursor = try Cursor.init(&seat);
|
||||||
|
|
||||||
// Set up handler for all new input devices made available. This
|
// Set up handler for all new input devices made available. This
|
||||||
// includes keyboards, pointers, touch, etc.
|
// includes keyboards, pointers, touch, etc.
|
||||||
c.wl_signal_add(&server.*.backend.*.events.new_input, &seat.new_input);
|
c.wl_signal_add(&server.wlr_backend.events.new_input, &seat.listen_new_input);
|
||||||
|
|
||||||
|
return seat;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_keyboard(self: *@This(), device: *c.wlr_input_device) void {
|
fn add_keyboard(self: *@This(), device: *c.wlr_input_device) !void {
|
||||||
self.keyboards.append(Keyboard.init(self, device));
|
try self.keyboards.append(Keyboard.init(self, device));
|
||||||
c.wlr_seat_set_keyboard(self, device);
|
c.wlr_seat_set_keyboard(self.wlr_seat, device);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_pointer(self: *@This(), device: *c.struct_wlr_input_device) void {
|
fn add_pointer(self: *@This(), device: *c.struct_wlr_input_device) void {
|
||||||
|
@ -53,7 +59,7 @@ pub const Seat = struct {
|
||||||
var device = @ptrCast(*c.wlr_input_device, @alignCast(@alignOf(*c.wlr_input_device), data));
|
var device = @ptrCast(*c.wlr_input_device, @alignCast(@alignOf(*c.wlr_input_device), data));
|
||||||
|
|
||||||
switch (device.*.type) {
|
switch (device.*.type) {
|
||||||
.WLR_INPUT_DEVICE_KEYBOARD => seat.add_keyboard(device),
|
.WLR_INPUT_DEVICE_KEYBOARD => seat.add_keyboard(device) catch unreachable,
|
||||||
.WLR_INPUT_DEVICE_POINTER => seat.add_pointer(device),
|
.WLR_INPUT_DEVICE_POINTER => seat.add_pointer(device),
|
||||||
else => {},
|
else => {},
|
||||||
}
|
}
|
||||||
|
@ -63,9 +69,9 @@ pub const Seat = struct {
|
||||||
// there are no pointer devices, so we always include that capability.
|
// there are no pointer devices, so we always include that capability.
|
||||||
var caps: u32 = @intCast(u32, c.WL_SEAT_CAPABILITY_POINTER);
|
var caps: u32 = @intCast(u32, c.WL_SEAT_CAPABILITY_POINTER);
|
||||||
// if list not empty
|
// if list not empty
|
||||||
if (c.wl_list_empty(&server.*.keyboards) == 0) {
|
if (seat.keyboards.span().len > 0) {
|
||||||
caps |= @intCast(u32, c.WL_SEAT_CAPABILITY_KEYBOARD);
|
caps |= @intCast(u32, c.WL_SEAT_CAPABILITY_KEYBOARD);
|
||||||
}
|
}
|
||||||
c.wlr_seat_set_capabilities(server.*.seat, caps);
|
c.wlr_seat_set_capabilities(seat.wlr_seat, caps);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const c = @import("c.zig").c;
|
const c = @import("c.zig").c;
|
||||||
|
|
||||||
|
const Output = @import("output.zig").Output;
|
||||||
|
const Seat = @import("seat.zig").Seat;
|
||||||
|
const View = @import("view.zig").View;
|
||||||
|
|
||||||
pub const Server = struct {
|
pub const Server = struct {
|
||||||
wl_display: *c.wl_display,
|
wl_display: *c.wl_display,
|
||||||
wlr_backend: *c.wlr_backend,
|
wlr_backend: *c.wlr_backend,
|
||||||
|
@ -17,8 +21,10 @@ pub const Server = struct {
|
||||||
// Must stay ordered bottom to top
|
// Must stay ordered bottom to top
|
||||||
views: std.ArrayList(View),
|
views: std.ArrayList(View),
|
||||||
|
|
||||||
|
seat: Seat,
|
||||||
|
|
||||||
pub fn init(allocator: *std.mem.Allocator) !@This() {
|
pub fn init(allocator: *std.mem.Allocator) !@This() {
|
||||||
var server = undefined;
|
var server: @This() = undefined;
|
||||||
|
|
||||||
// The Wayland display is managed by libwayland. It handles accepting
|
// The Wayland display is managed by libwayland. It handles accepting
|
||||||
// clients from the Unix socket, manging Wayland globals, and so on.
|
// clients from the Unix socket, manging Wayland globals, and so on.
|
||||||
|
@ -31,19 +37,20 @@ pub const Server = struct {
|
||||||
// a tty or wayland if WAYLAND_DISPLAY is set.
|
// a tty or wayland if WAYLAND_DISPLAY is set.
|
||||||
//
|
//
|
||||||
// This frees itself when the wl_display is destroyed.
|
// This frees itself when the wl_display is destroyed.
|
||||||
server.wlr_backend = c.wlr_backend_autocreate(server.wl_display) orelse
|
server.wlr_backend = c.zag_wlr_backend_autocreate(server.wl_display) orelse
|
||||||
return error.CantCreateWlrBackend;
|
return error.CantCreateWlrBackend;
|
||||||
|
|
||||||
// If we don't provide a renderer, autocreate makes a GLES2 renderer for us.
|
// 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
|
// The renderer is responsible for defining the various pixel formats it
|
||||||
// supports for shared memory, this configures that for clients.
|
// supports for shared memory, this configures that for clients.
|
||||||
server.wlr_renderer = c.wlr_backend_get_renderer(server.backend) orelse
|
server.wlr_renderer = c.zag_wlr_backend_get_renderer(server.wlr_backend) orelse
|
||||||
return error.CantGetWlrRenderer;
|
return error.CantGetWlrRenderer;
|
||||||
c.wlr_renderer_init_wl_display(server.wlr_renderer, server.wl_display) orelse
|
// TODO: Handle failure after https://github.com/swaywm/wlroots/pull/2080
|
||||||
return error.CantInitWlDisplay;
|
c.wlr_renderer_init_wl_display(server.wlr_renderer, server.wl_display);// orelse
|
||||||
|
// return error.CantInitWlDisplay;
|
||||||
|
|
||||||
// These both free themselves when the wl_display is destroyed
|
// These both free themselves when the wl_display is destroyed
|
||||||
_ = c.wlr_compositor_create(server.wl_display, server.renderer) orelse
|
_ = c.wlr_compositor_create(server.wl_display, server.wlr_renderer) orelse
|
||||||
return error.CantCreateWlrCompositor;
|
return error.CantCreateWlrCompositor;
|
||||||
_ = c.wlr_data_device_manager_create(server.wl_display) orelse
|
_ = c.wlr_data_device_manager_create(server.wl_display) orelse
|
||||||
return error.CantCreateWlrDataDeviceManager;
|
return error.CantCreateWlrDataDeviceManager;
|
||||||
|
@ -57,7 +64,7 @@ pub const Server = struct {
|
||||||
server.outputs = std.ArrayList(Output).init(std.heap.c_allocator);
|
server.outputs = std.ArrayList(Output).init(std.heap.c_allocator);
|
||||||
|
|
||||||
// Setup a listener for new outputs
|
// Setup a listener for new outputs
|
||||||
server.listen_new_output = handle_new_output;
|
server.listen_new_output.notify = handle_new_output;
|
||||||
c.wl_signal_add(&server.wlr_backend.*.events.new_output, &server.listen_new_output);
|
c.wl_signal_add(&server.wlr_backend.*.events.new_output, &server.listen_new_output);
|
||||||
|
|
||||||
// Set up our list of views and the xdg-shell. The xdg-shell is a Wayland
|
// Set up our list of views and the xdg-shell. The xdg-shell is a Wayland
|
||||||
|
@ -67,7 +74,9 @@ pub const Server = struct {
|
||||||
server.wlr_xdg_shell = c.wlr_xdg_shell_create(server.wl_display) orelse
|
server.wlr_xdg_shell = c.wlr_xdg_shell_create(server.wl_display) orelse
|
||||||
return error.CantCreateWlrXdgShell;
|
return error.CantCreateWlrXdgShell;
|
||||||
server.listen_new_xdg_surface.notify = handle_new_xdg_surface;
|
server.listen_new_xdg_surface.notify = handle_new_xdg_surface;
|
||||||
c.wl_signal_add(&server.xdg_shell.*.events.new_surface, &server.listen_new_xdg_surface);
|
c.wl_signal_add(&server.wlr_xdg_shell.*.events.new_surface, &server.listen_new_xdg_surface);
|
||||||
|
|
||||||
|
server.seat = try Seat.init(&server, std.heap.c_allocator);
|
||||||
|
|
||||||
return server;
|
return server;
|
||||||
}
|
}
|
||||||
|
@ -87,8 +96,7 @@ pub const Server = struct {
|
||||||
|
|
||||||
// Start the backend. This will enumerate outputs and inputs, become the DRM
|
// Start the backend. This will enumerate outputs and inputs, become the DRM
|
||||||
// master, etc
|
// master, etc
|
||||||
if (!c.wlr_backend_start(self.wlr_backend)) {
|
if (!c.zag_wlr_backend_start(self.wlr_backend)) {
|
||||||
c.wlr_backend_destroy(self.wlr_backend);
|
|
||||||
return error.CantStartBackend;
|
return error.CantStartBackend;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,7 +109,7 @@ pub const Server = struct {
|
||||||
|
|
||||||
/// Enter the wayland event loop and block until the compositor is exited
|
/// Enter the wayland event loop and block until the compositor is exited
|
||||||
pub fn run(self: @This()) void {
|
pub fn run(self: @This()) void {
|
||||||
c.wl_display_run(server.wl_display);
|
c.wl_display_run(self.wl_display);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_keybinding(self: *@This(), sym: c.xkb_keysym_t) bool {
|
pub fn handle_keybinding(self: *@This(), sym: c.xkb_keysym_t) bool {
|
||||||
|
@ -111,7 +119,7 @@ pub const Server = struct {
|
||||||
//
|
//
|
||||||
// This function assumes the proper modifier is held down.
|
// This function assumes the proper modifier is held down.
|
||||||
switch (sym) {
|
switch (sym) {
|
||||||
c.XKB_KEY_Escape => c.wl_display_terminate(server.*.wl_display),
|
c.XKB_KEY_Escape => c.wl_display_terminate(self.wl_display),
|
||||||
c.XKB_KEY_F1 => {
|
c.XKB_KEY_F1 => {
|
||||||
// Cycle to the next view
|
// Cycle to the next view
|
||||||
//if (c.wl_list_length(&server.*.views) > 1) {
|
//if (c.wl_list_length(&server.*.views) > 1) {
|
||||||
|
@ -129,11 +137,11 @@ pub const Server = struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_new_output(listener: [*c]c.wl_listener, data: ?*c_void) callconv(.C) void {
|
fn handle_new_output(listener: [*c]c.wl_listener, data: ?*c_void) callconv(.C) void {
|
||||||
var server = @fieldParentPtr(Server, "new_output", listener);
|
var server = @fieldParentPtr(Server, "listen_new_output", listener);
|
||||||
var wlr_output = @ptrCast(*c.wlr_output, @alignCast(@alignOf(*c.wlr_output), data));
|
var wlr_output = @ptrCast(*c.wlr_output, @alignCast(@alignOf(*c.wlr_output), data));
|
||||||
|
|
||||||
// TODO: Handle failure
|
// TODO: Handle failure
|
||||||
server.outputs.append(Output.init(server, wlr_output) catch unreachable);
|
server.outputs.append(Output.init(server, wlr_output) catch unreachable) catch unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_new_xdg_surface(listener: [*c]c.wl_listener, data: ?*c_void) callconv(.C) void {
|
fn handle_new_xdg_surface(listener: [*c]c.wl_listener, data: ?*c_void) callconv(.C) void {
|
||||||
|
@ -153,7 +161,7 @@ pub const Server = struct {
|
||||||
/// Finds the top most view under the output layout coordinates lx, ly
|
/// Finds the top most view under the output layout coordinates lx, ly
|
||||||
/// returns the view if found, and a pointer to the wlr_surface as well as the surface coordinates
|
/// returns the view if found, and a pointer to the wlr_surface as well as the surface coordinates
|
||||||
pub fn desktop_view_at(self: *@This(), lx: f64, ly: f64, surface: *?*c.wlr_surface, sx: *f64, sy: *f64) ?*View {
|
pub fn desktop_view_at(self: *@This(), lx: f64, ly: f64, surface: *?*c.wlr_surface, sx: *f64, sy: *f64) ?*View {
|
||||||
for (server.*.views.span()) |*view| {
|
for (self.views.span()) |*view| {
|
||||||
if (view.is_at(lx, ly, surface, sx, sy)) {
|
if (view.is_at(lx, ly, surface, sx, sy)) {
|
||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
|
|
55
src/view.zig
55
src/view.zig
|
@ -1,6 +1,8 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const c = @import("c.zig").c;
|
const c = @import("c.zig").c;
|
||||||
|
|
||||||
|
const Server = @import("server.zig").Server;
|
||||||
|
|
||||||
pub const View = struct {
|
pub const View = struct {
|
||||||
server: *Server,
|
server: *Server,
|
||||||
wlr_xdg_surface: *c.wlr_xdg_surface,
|
wlr_xdg_surface: *c.wlr_xdg_surface,
|
||||||
|
@ -39,12 +41,15 @@ pub const View = struct {
|
||||||
// .link = undefined,
|
// .link = undefined,
|
||||||
// .notify = handle_request_resize,
|
// .notify = handle_request_resize,
|
||||||
// },
|
// },
|
||||||
|
.mapped = false,
|
||||||
|
.x = 0,
|
||||||
|
.y = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Listen to the various events it can emit
|
// Listen to the various events it can emit
|
||||||
c.wl_signal_add(&xdg_surface.*.events.map, &view.*.listen_map);
|
c.wl_signal_add(&view.wlr_xdg_surface.events.map, &view.listen_map);
|
||||||
c.wl_signal_add(&xdg_surface.*.events.unmap, &view.*.listen_unmap);
|
c.wl_signal_add(&view.wlr_xdg_surface.events.unmap, &view.listen_unmap);
|
||||||
c.wl_signal_add(&xdg_surface.*.events.destroy, &view.*.listen_destroy);
|
c.wl_signal_add(&view.wlr_xdg_surface.events.destroy, &view.listen_destroy);
|
||||||
|
|
||||||
// var toplevel = xdg_surface.*.unnamed_160.toplevel;
|
// var toplevel = xdg_surface.*.unnamed_160.toplevel;
|
||||||
// c.wl_signal_add(&toplevel.*.events.request_move, &view.*.request_move);
|
// c.wl_signal_add(&toplevel.*.events.request_move, &view.*.request_move);
|
||||||
|
@ -55,18 +60,18 @@ pub const View = struct {
|
||||||
|
|
||||||
fn handle_map(listener: [*c]c.wl_listener, data: ?*c_void) callconv(.C) void {
|
fn handle_map(listener: [*c]c.wl_listener, data: ?*c_void) callconv(.C) void {
|
||||||
// Called when the surface is mapped, or ready to display on-screen.
|
// Called when the surface is mapped, or ready to display on-screen.
|
||||||
var view = @fieldParentPtr(View, "map", listener);
|
var view = @fieldParentPtr(View, "listen_map", listener);
|
||||||
view.*.mapped = true;
|
view.mapped = true;
|
||||||
focus_view(view, view.*.xdg_surface.*.surface);
|
view.focus(view.wlr_xdg_surface.surface);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_unmap(listener: [*c]c.wl_listener, data: ?*c_void) callconv(.C) void {
|
fn handle_unmap(listener: [*c]c.wl_listener, data: ?*c_void) callconv(.C) void {
|
||||||
var view = @fieldParentPtr(View, "unmap", listener);
|
var view = @fieldParentPtr(View, "listen_unmap", listener);
|
||||||
view.*.mapped = false;
|
view.*.mapped = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_destroy(listener: [*c]c.wl_listener, data: ?*c_void) callconv(.C) void {
|
fn handle_destroy(listener: [*c]c.wl_listener, data: ?*c_void) callconv(.C) void {
|
||||||
var view = @fieldParentPtr(View, "destroy", listener);
|
var view = @fieldParentPtr(View, "listen_destroy", listener);
|
||||||
var server = view.*.server;
|
var server = view.*.server;
|
||||||
const idx = for (server.*.views.span()) |*v, i| {
|
const idx = for (server.*.views.span()) |*v, i| {
|
||||||
if (v == view) {
|
if (v == view) {
|
||||||
|
@ -84,10 +89,10 @@ pub const View = struct {
|
||||||
// // ignore for now
|
// // ignore for now
|
||||||
// }
|
// }
|
||||||
|
|
||||||
fn focus_view(view: *View, surface: *c.wlr_surface) void {
|
fn focus(self: *@This(), surface: *c.wlr_surface) void {
|
||||||
const server = view.server;
|
const server = self.server;
|
||||||
const seat = server.*.seat;
|
const wlr_seat = server.seat.wlr_seat;
|
||||||
const prev_surface = seat.*.keyboard_state.focused_surface;
|
const prev_surface = wlr_seat.keyboard_state.focused_surface;
|
||||||
|
|
||||||
if (prev_surface == surface) {
|
if (prev_surface == surface) {
|
||||||
// Don't re-focus an already focused surface.
|
// Don't re-focus an already focused surface.
|
||||||
|
@ -103,25 +108,31 @@ pub const View = struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find the index
|
// Find the index
|
||||||
const idx = for (server.*.views.span()) |*v, i| {
|
const idx = for (server.views.span()) |*v, i| {
|
||||||
if (v == view) {
|
if (self == v) {
|
||||||
break i;
|
break i;
|
||||||
}
|
}
|
||||||
} else unreachable;
|
} else unreachable;
|
||||||
|
|
||||||
// Move the view to the front
|
// Move the view to the front
|
||||||
server.*.views.append(server.*.views.orderedRemove(idx)) catch unreachable;
|
server.views.append(server.views.orderedRemove(idx)) catch unreachable;
|
||||||
|
|
||||||
var moved_view = &server.*.views.span()[server.*.views.span().len - 1];
|
var moved_self = &server.views.span()[server.views.span().len - 1];
|
||||||
|
|
||||||
// Activate the new surface
|
// Activate the new surface
|
||||||
_ = c.wlr_xdg_toplevel_set_activated(moved_view.*.xdg_surface, true);
|
_ = c.wlr_xdg_toplevel_set_activated(moved_self.wlr_xdg_surface, true);
|
||||||
|
|
||||||
// Tell the seat to have the keyboard enter this surface. wlroots will keep
|
// Tell the seat to have the keyboard enter this surface. wlroots will keep
|
||||||
// track of this and automatically send key events to the appropriate
|
// track of this and automatically send key events to the appropriate
|
||||||
// clients without additional work on your part.
|
// clients without additional work on your part.
|
||||||
var keyboard = c.wlr_seat_get_keyboard(seat);
|
var keyboard = c.wlr_seat_get_keyboard(wlr_seat);
|
||||||
c.wlr_seat_keyboard_notify_enter(seat, moved_view.*.xdg_surface.*.surface, &keyboard.*.keycodes, keyboard.*.num_keycodes, &keyboard.*.modifiers);
|
c.wlr_seat_keyboard_notify_enter(
|
||||||
|
wlr_seat,
|
||||||
|
moved_self.wlr_xdg_surface.surface,
|
||||||
|
&keyboard.*.keycodes,
|
||||||
|
keyboard.*.num_keycodes,
|
||||||
|
&keyboard.*.modifiers,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_at(self: *@This(), lx: f64, ly: f64, surface: *?*c.wlr_surface, sx: *f64, sy: *f64) bool {
|
fn is_at(self: *@This(), lx: f64, ly: f64, surface: *?*c.wlr_surface, sx: *f64, sy: *f64) bool {
|
||||||
|
@ -130,15 +141,15 @@ pub const View = struct {
|
||||||
// coordinates lx and ly (in output Layout Coordinates). If so, it sets 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
|
// surface pointer to that wlr_surface and the sx and sy coordinates to the
|
||||||
// coordinates relative to that surface's top-left corner.
|
// coordinates relative to that surface's top-left corner.
|
||||||
var view_sx = lx - @intToFloat(f64, view.*.x);
|
var view_sx = lx - @intToFloat(f64, self.x);
|
||||||
var view_sy = ly - @intToFloat(f64, view.*.y);
|
var view_sy = ly - @intToFloat(f64, self.y);
|
||||||
|
|
||||||
// This variable seems to have been unsued in TinyWL
|
// This variable seems to have been unsued in TinyWL
|
||||||
// struct wlr_surface_state *state = &view->xdg_surface->surface->current;
|
// struct wlr_surface_state *state = &view->xdg_surface->surface->current;
|
||||||
|
|
||||||
var _sx: f64 = undefined;
|
var _sx: f64 = undefined;
|
||||||
var _sy: f64 = undefined;
|
var _sy: f64 = undefined;
|
||||||
var _surface = c.wlr_xdg_surface_surface_at(view.*.xdg_surface, view_sx, view_sy, &_sx, &_sy);
|
var _surface = c.wlr_xdg_surface_surface_at(self.wlr_xdg_surface, view_sx, view_sy, &_sx, &_sy);
|
||||||
|
|
||||||
if (_surface) |surface_at| {
|
if (_surface) |surface_at| {
|
||||||
sx.* = _sx;
|
sx.* = _sx;
|
||||||
|
|
Loading…
Reference in a new issue