diff options
Diffstat (limited to 'src/cursor.zig')
| -rw-r--r-- | src/cursor.zig | 151 |
1 files changed, 77 insertions, 74 deletions
diff --git a/src/cursor.zig b/src/cursor.zig index 2ef9fab..a7e4c98 100644 --- a/src/cursor.zig +++ b/src/cursor.zig @@ -1,6 +1,9 @@ const std = @import("std"); const c = @import("c.zig").c; +const Seat = @import("seat.zig").Seat; +const View = @import("view.zig").View; + const CursorMode = enum { Passthrough, Move, @@ -19,9 +22,9 @@ pub const Cursor = struct { listen_axis: 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, grab_x: f64, grab_y: f64, @@ -31,7 +34,6 @@ pub const Cursor = struct { pub fn init(seat: *Seat) !@This() { var cursor = @This(){ - .server = seat.server, .seat = seat, // Creates a wlroots utility for tracking the cursor image shown on screen. @@ -81,8 +83,8 @@ pub const Cursor = struct { .resize_edges = 0, }; - c.wlr_cursor_attach_output_layout(cursor.wlr_cursor, seat.*.server.*.output_layout); - _ = c.wlr_xcursor_manager_load(server.cursor_mgr, 1); + c.wlr_cursor_attach_output_layout(cursor.wlr_cursor, seat.server.wlr_output_layout); + _ = c.wlr_xcursor_manager_load(cursor.wlr_xcursor_manager, 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 @@ -97,18 +99,18 @@ pub const Cursor = struct { c.wl_signal_add(&cursor.wlr_cursor.*.events.frame, &cursor.listen_frame); // 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; } - 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. - 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); + self.grabbed_view.?.*.x = @floatToInt(c_int, self.wlr_cursor.x - self.grab_x); + 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 // 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 @@ -117,61 +119,61 @@ pub const Cursor = struct { // 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); + // TODO: Handle null view + var view = self.grabbed_view; + + var dx: f64 = self.wlr_cursor.x - self.grab_x; + var dy: f64 = self.wlr_cursor.y - self.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; + 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; if (height < 1) { 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; } - if (server.*.resize_edges & @intCast(u32, c.WLR_EDGE_LEFT) != 0) { - x = server.*.grab_x + dx; + if (self.resize_edges & @intCast(u32, c.WLR_EDGE_LEFT) != 0) { + x = self.grab_x + dx; width -= dx; if (width < 1) { 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; } - view.?.*.x = @floatToInt(c_int, x); - view.?.*.y = @floatToInt(c_int, y); + view.?.x = @floatToInt(c_int, x); + view.?.y = @floatToInt(c_int, y); _ = c.wlr_xdg_toplevel_set_size( - view.?.*.xdg_surface, + view.?.wlr_xdg_surface, @floatToInt(u32, width), @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 (server.*.cursor_mode == CursorMode.Move) { - process_cursor_move(server, time); + if (self.mode == CursorMode.Move) { + self.process_move(time); return; - } else if (server.*.cursor_mode == CursorMode.Resize) { - process_cursor_resize(server, time); + } else if (self.mode == CursorMode.Resize) { + self.process_resize(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, + var view = self.seat.server.desktop_view_at( + self.wlr_cursor.x, + self.wlr_cursor.y, &opt_surface, &sx, &sy, @@ -182,37 +184,38 @@ pub const Cursor = struct { // 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, + self.wlr_xcursor_manager, "left_ptr", - server.*.cursor, + self.wlr_cursor, ); } + var wlr_seat = self.seat.wlr_seat; 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 // 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); + c.wlr_seat_pointer_notify_enter(wlr_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); + c.wlr_seat_pointer_notify_motion(wlr_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); + c.wlr_seat_pointer_clear_focus(wlr_seat); } } 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_ // pointer motion event (i.e. a delta) - var server = @fieldParentPtr(Server, "cursor_motion", listener); + var cursor = @fieldParentPtr(Cursor, "listen_motion", listener); var event = @ptrCast( *c.wlr_event_pointer_motion, @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 // 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); + c.wlr_cursor_move(cursor.wlr_cursor, event.device, event.delta_x, event.delta_y); + cursor.process_motion(event.time_msec); } 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, // 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 cursor = @fieldParentPtr(Cursor, "listen_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); + c.wlr_cursor_warp_absolute(cursor.wlr_cursor, event.device, event.x, event.y); + cursor.process_motion(event.time_msec); } 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 // event. - var server = @fieldParentPtr(Server, "cursor_button", listener); + var cursor = @fieldParentPtr(Cursor, "listen_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, + cursor.seat.wlr_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, + var view = cursor.seat.server.desktop_view_at( + cursor.wlr_cursor.x, + cursor.wlr_cursor.y, &surface, &sx, &sy, @@ -273,11 +275,11 @@ pub const Cursor = struct { 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; + cursor.mode = CursorMode.Passthrough; } else { // Focus that client if the button was _pressed_ 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 { // 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 cursor = @fieldParentPtr(Cursor, "listen_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, + cursor.seat.wlr_seat, + event.time_msec, + event.orientation, + event.delta, + event.delta_discrete, + event.source, ); } @@ -306,19 +309,19 @@ pub const Cursor = struct { // 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); + var cursor = @fieldParentPtr(Cursor, "listen_frame", listener); // 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 { // 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( *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; + 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 // 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 // cursor moves between outputs. c.wlr_cursor_set_surface( - server.*.cursor, - event.*.surface, - event.*.hotspot_x, - event.*.hotspot_y, + cursor.wlr_cursor, + event.surface, + event.hotspot_x, + event.hotspot_y, ); } } |
