aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeon Henrik Plickat <leonhenrik.plickat@stud.uni-goettingen.de>2020-10-17 22:40:15 +0200
committerIsaac Freund <ifreund@ifreund.xyz>2020-10-17 23:42:37 +0200
commitec5d5e8826d0370587b6209dcdb2ad9ba9ab4d54 (patch)
treea0188b6357e826c2abf5e87cb41fc2c648446b79
parentd5d1e87a955599c54509c5212fae1b5043ebee29 (diff)
downloadriver-ec5d5e8826d0370587b6209dcdb2ad9ba9ab4d54.tar.gz
river-ec5d5e8826d0370587b6209dcdb2ad9ba9ab4d54.tar.xz
Move Cursor.Mode impl functions to Cursor
-rw-r--r--river/Cursor.zig374
-rw-r--r--river/XdgToplevel.zig5
2 files changed, 189 insertions, 190 deletions
diff --git a/river/Cursor.zig b/river/Cursor.zig
index 4e28221..e58c42b 100644
--- a/river/Cursor.zig
+++ b/river/Cursor.zig
@@ -33,7 +33,7 @@ const Seat = @import("Seat.zig");
const View = @import("View.zig");
const ViewStack = @import("view_stack.zig").ViewStack;
-pub const Mode = union(enum) {
+const Mode = union(enum) {
passthrough: void,
down: *View,
move: *View,
@@ -43,187 +43,13 @@ pub const Mode = union(enum) {
offset_x: i32,
offset_y: i32,
},
-
- /// Enter move or resize mode
- pub fn enter(self: *Self, mode: @TagType(Mode), view: *View) void {
- log.debug(.cursor, "enter {} mode", .{@tagName(mode)});
-
- self.seat.focus(view);
-
- switch (mode) {
- .passthrough => unreachable,
- .down => {
- self.mode = .{ .down = view };
- view.output.root.startTransaction();
- },
- .move, .resize => {
- const cur_box = &view.current.box;
- self.mode = switch (mode) {
- .passthrough, .down => unreachable,
- .move => .{ .move = view },
- .resize => .{
- .resize = .{
- .view = view,
- .offset_x = cur_box.x + @intCast(i32, cur_box.width) - @floatToInt(i32, self.wlr_cursor.x),
- .offset_y = cur_box.y + @intCast(i32, cur_box.height) - @floatToInt(i32, self.wlr_cursor.y),
- },
- },
- };
-
- // Automatically float all views being moved by the pointer
- if (!view.current.float) {
- view.pending.float = true;
- view.float_box = view.current.box;
- view.applyPending();
- }
-
- // Clear cursor focus, so that the surface does not receive events
- c.wlr_seat_pointer_clear_focus(self.seat.wlr_seat);
-
- c.wlr_xcursor_manager_set_cursor_image(
- self.wlr_xcursor_manager,
- if (mode == .move) "move" else "se-resize",
- self.wlr_cursor,
- );
- },
- }
- }
-
- /// Return from down/move/resize to passthrough
- fn leave(self: *Self, event: *c.wlr_event_pointer_button) void {
- std.debug.assert(self.mode != .passthrough);
-
- log.debug(.cursor, "leave {} mode", .{@tagName(self.mode)});
-
- // If we were in down mode, we need pass along the release event
- if (self.mode == .down)
- _ = c.wlr_seat_pointer_notify_button(
- self.seat.wlr_seat,
- event.time_msec,
- event.button,
- event.state,
- );
-
- self.mode = .passthrough;
- passthrough(self, event.time_msec);
- }
-
- fn processMotion(self: *Self, device: *c.wlr_input_device, time: u32, delta_x: f64, delta_y: f64) void {
- const config = self.seat.input_manager.server.config;
-
- switch (self.mode) {
- .passthrough => {
- c.wlr_cursor_move(self.wlr_cursor, device, delta_x, delta_y);
- passthrough(self, time);
- },
- .down => |view| {
- c.wlr_cursor_move(self.wlr_cursor, device, delta_x, delta_y);
- c.wlr_seat_pointer_notify_motion(
- self.seat.wlr_seat,
- time,
- self.wlr_cursor.x - @intToFloat(f64, view.current.box.x),
- self.wlr_cursor.y - @intToFloat(f64, view.current.box.y),
- );
- },
- .move => |view| {
- const border_width = if (view.draw_borders) config.border_width else 0;
-
- // Set x/y of cursor and view, clamp to output dimensions
- const output_resolution = view.output.getEffectiveResolution();
- view.pending.box.x = std.math.clamp(
- view.pending.box.x + @floatToInt(i32, delta_x),
- @intCast(i32, border_width),
- @intCast(i32, output_resolution.width - view.pending.box.width - border_width),
- );
- view.pending.box.y = std.math.clamp(
- view.pending.box.y + @floatToInt(i32, delta_y),
- @intCast(i32, border_width),
- @intCast(i32, output_resolution.height - view.pending.box.height - border_width),
- );
-
- c.wlr_cursor_move(
- self.wlr_cursor,
- device,
- @intToFloat(f64, view.pending.box.x - view.current.box.x),
- @intToFloat(f64, view.pending.box.y - view.current.box.y),
- );
-
- view.applyPending();
- },
- .resize => |data| {
- const border_width = if (data.view.draw_borders) config.border_width else 0;
-
- // Set width/height of view, clamp to view size constraints and output dimensions
- const box = &data.view.pending.box;
- box.width = @intCast(u32, std.math.max(0, @intCast(i32, box.width) + @floatToInt(i32, delta_x)));
- box.height = @intCast(u32, std.math.max(0, @intCast(i32, box.height) + @floatToInt(i32, delta_y)));
-
- data.view.applyConstraints();
-
- const output_resolution = data.view.output.getEffectiveResolution();
- box.width = std.math.min(box.width, output_resolution.width - border_width - @intCast(u32, box.x));
- box.height = std.math.min(box.height, output_resolution.height - border_width - @intCast(u32, box.y));
-
- data.view.applyPending();
-
- // Keep cursor locked to the original offset from the bottom right corner
- c.wlr_cursor_warp_closest(
- self.wlr_cursor,
- device,
- @intToFloat(f64, box.x + @intCast(i32, box.width) - data.offset_x),
- @intToFloat(f64, box.y + @intCast(i32, box.height) - data.offset_y),
- );
- },
- }
- }
-
- /// Pass an event on to the surface under the cursor, if any.
- fn passthrough(self: *Self, time: u32) void {
- const root = &self.seat.input_manager.server.root;
- const config = self.seat.input_manager.server.config;
-
- var sx: f64 = undefined;
- var sy: f64 = undefined;
- if (self.surfaceAt(self.wlr_cursor.x, self.wlr_cursor.y, &sx, &sy)) |wlr_surface| {
- // If input is allowed on the surface, send pointer enter and motion
- // events. Note that wlroots won't actually send an enter event if
- // the surface has already been entered.
- if (self.seat.input_manager.inputAllowed(wlr_surface)) {
- // The focus change must be checked before sending enter events
- const focus_change = self.seat.wlr_seat.pointer_state.focused_surface != wlr_surface;
-
- c.wlr_seat_pointer_notify_enter(self.seat.wlr_seat, wlr_surface, sx, sy);
- c.wlr_seat_pointer_notify_motion(self.seat.wlr_seat, time, sx, sy);
- if (View.fromWlrSurface(wlr_surface)) |view| {
- // Change focus according to config
- switch (config.focus_follows_cursor) {
- .disabled => {},
- .normal => {
- // Only refocus when the cursor entered a new surface
- if (focus_change) {
- self.seat.focus(view);
- root.startTransaction();
- }
- },
- .strict => {
- self.seat.focus(view);
- root.startTransaction();
- },
- }
- }
-
- return;
- }
- } else {
- // There is either no surface under the cursor or input is disallowed
- // Reset the cursor image to the default and clear focus.
- self.clearFocus();
- }
- }
};
const default_size = 24;
+/// Current cursor mode as well as any state needed to implement that mode
+mode: Mode = .passthrough,
+
seat: *Seat,
wlr_cursor: *c.wlr_cursor,
wlr_xcursor_manager: *c.wlr_xcursor_manager,
@@ -231,9 +57,6 @@ wlr_xcursor_manager: *c.wlr_xcursor_manager,
/// Number of distinct buttons currently pressed
pressed_count: u32 = 0,
-/// Current cursor mode as well as any state needed to implement that mode
-mode: Mode = .passthrough,
-
listen_axis: c.wl_listener = undefined,
listen_button: c.wl_listener = undefined,
listen_frame: c.wl_listener = undefined,
@@ -392,7 +215,7 @@ fn handleButton(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) void {
std.debug.assert(self.pressed_count > 0);
self.pressed_count -= 1;
if (self.pressed_count == 0 and self.mode != .passthrough) {
- Mode.leave(self, event);
+ self.leaveMode(event);
return;
}
}
@@ -418,7 +241,7 @@ fn handleButton(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) void {
// handled we are done here
if (self.handlePointerMapping(event, view)) return;
// Otherwise enter cursor down mode
- Mode.enter(self, .down, view);
+ self.enterMode(.down, view);
}
}
@@ -443,8 +266,8 @@ fn handlePointerMapping(self: *Self, event: *c.wlr_event_pointer_button, view: *
return for (config.modes.items[self.seat.mode_id].pointer_mappings.items) |mapping| {
if (event.button == mapping.event_code and modifiers == mapping.modifiers) {
switch (mapping.action) {
- .move => if (!fullscreen) Mode.enter(self, .move, view),
- .resize => if (!fullscreen) Mode.enter(self, .resize, view),
+ .move => if (!fullscreen) self.enterMode(.move, view),
+ .resize => if (!fullscreen) self.enterMode(.resize, view),
}
break true;
}
@@ -477,7 +300,7 @@ fn handleMotionAbsolute(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C)
var ly: f64 = undefined;
c.wlr_cursor_absolute_to_layout_coords(self.wlr_cursor, event.device, event.x, event.y, &lx, &ly);
- Mode.processMotion(self, event.device, event.time_msec, lx - self.wlr_cursor.x, ly - self.wlr_cursor.y);
+ self.processMotion(event.device, event.time_msec, lx - self.wlr_cursor.x, ly - self.wlr_cursor.y);
}
fn handleMotion(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) void {
@@ -488,7 +311,7 @@ fn handleMotion(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) void {
self.seat.handleActivity();
- Mode.processMotion(self, event.device, event.time_msec, event.delta_x, event.delta_y);
+ self.processMotion(event.device, event.time_msec, event.delta_x, event.delta_y);
}
fn handleRequestSetCursor(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) void {
@@ -611,3 +434,180 @@ fn viewSurfaceAt(output: Output, ox: f64, oy: f64, sx: *f64, sy: *f64) ?*c.wlr_s
fn surfaceAtFilter(view: *View, filter_tags: u32) bool {
return !view.destroying and view.current.tags & filter_tags != 0;
}
+
+/// Enter move or resize mode
+pub fn enterMode(self: *Self, mode: @TagType(Mode), view: *View) void {
+ log.debug(.cursor, "enter {} mode", .{@tagName(mode)});
+
+ self.seat.focus(view);
+
+ switch (mode) {
+ .passthrough => unreachable,
+ .down => {
+ self.mode = .{ .down = view };
+ view.output.root.startTransaction();
+ },
+ .move, .resize => {
+ const cur_box = &view.current.box;
+ self.mode = switch (mode) {
+ .passthrough, .down => unreachable,
+ .move => .{ .move = view },
+ .resize => .{
+ .resize = .{
+ .view = view,
+ .offset_x = cur_box.x + @intCast(i32, cur_box.width) - @floatToInt(i32, self.wlr_cursor.x),
+ .offset_y = cur_box.y + @intCast(i32, cur_box.height) - @floatToInt(i32, self.wlr_cursor.y),
+ },
+ },
+ };
+
+ // Automatically float all views being moved by the pointer
+ if (!view.current.float) {
+ view.pending.float = true;
+ view.float_box = view.current.box;
+ view.applyPending();
+ }
+
+ // Clear cursor focus, so that the surface does not receive events
+ c.wlr_seat_pointer_clear_focus(self.seat.wlr_seat);
+
+ c.wlr_xcursor_manager_set_cursor_image(
+ self.wlr_xcursor_manager,
+ if (mode == .move) "move" else "se-resize",
+ self.wlr_cursor,
+ );
+ },
+ }
+}
+
+/// Return from down/move/resize to passthrough
+fn leaveMode(self: *Self, event: *c.wlr_event_pointer_button) void {
+ std.debug.assert(self.mode != .passthrough);
+
+ log.debug(.cursor, "leave {} mode", .{@tagName(self.mode)});
+
+ // If we were in down mode, we need pass along the release event
+ if (self.mode == .down)
+ _ = c.wlr_seat_pointer_notify_button(
+ self.seat.wlr_seat,
+ event.time_msec,
+ event.button,
+ event.state,
+ );
+
+ self.mode = .passthrough;
+ self.passthrough(event.time_msec);
+}
+
+fn processMotion(self: *Self, device: *c.wlr_input_device, time: u32, delta_x: f64, delta_y: f64) void {
+ const config = self.seat.input_manager.server.config;
+
+ switch (self.mode) {
+ .passthrough => {
+ c.wlr_cursor_move(self.wlr_cursor, device, delta_x, delta_y);
+ self.passthrough(time);
+ },
+ .down => |view| {
+ c.wlr_cursor_move(self.wlr_cursor, device, delta_x, delta_y);
+ c.wlr_seat_pointer_notify_motion(
+ self.seat.wlr_seat,
+ time,
+ self.wlr_cursor.x - @intToFloat(f64, view.current.box.x),
+ self.wlr_cursor.y - @intToFloat(f64, view.current.box.y),
+ );
+ },
+ .move => |view| {
+ const border_width = if (view.draw_borders) config.border_width else 0;
+
+ // Set x/y of cursor and view, clamp to output dimensions
+ const output_resolution = view.output.getEffectiveResolution();
+ view.pending.box.x = std.math.clamp(
+ view.pending.box.x + @floatToInt(i32, delta_x),
+ @intCast(i32, border_width),
+ @intCast(i32, output_resolution.width - view.pending.box.width - border_width),
+ );
+ view.pending.box.y = std.math.clamp(
+ view.pending.box.y + @floatToInt(i32, delta_y),
+ @intCast(i32, border_width),
+ @intCast(i32, output_resolution.height - view.pending.box.height - border_width),
+ );
+
+ c.wlr_cursor_move(
+ self.wlr_cursor,
+ device,
+ @intToFloat(f64, view.pending.box.x - view.current.box.x),
+ @intToFloat(f64, view.pending.box.y - view.current.box.y),
+ );
+
+ view.applyPending();
+ },
+ .resize => |data| {
+ const border_width = if (data.view.draw_borders) config.border_width else 0;
+
+ // Set width/height of view, clamp to view size constraints and output dimensions
+ const box = &data.view.pending.box;
+ box.width = @intCast(u32, std.math.max(0, @intCast(i32, box.width) + @floatToInt(i32, delta_x)));
+ box.height = @intCast(u32, std.math.max(0, @intCast(i32, box.height) + @floatToInt(i32, delta_y)));
+
+ data.view.applyConstraints();
+
+ const output_resolution = data.view.output.getEffectiveResolution();
+ box.width = std.math.min(box.width, output_resolution.width - border_width - @intCast(u32, box.x));
+ box.height = std.math.min(box.height, output_resolution.height - border_width - @intCast(u32, box.y));
+
+ data.view.applyPending();
+
+ // Keep cursor locked to the original offset from the bottom right corner
+ c.wlr_cursor_warp_closest(
+ self.wlr_cursor,
+ device,
+ @intToFloat(f64, box.x + @intCast(i32, box.width) - data.offset_x),
+ @intToFloat(f64, box.y + @intCast(i32, box.height) - data.offset_y),
+ );
+ },
+ }
+}
+
+/// Pass an event on to the surface under the cursor, if any.
+fn passthrough(self: *Self, time: u32) void {
+ const root = &self.seat.input_manager.server.root;
+ const config = self.seat.input_manager.server.config;
+
+ var sx: f64 = undefined;
+ var sy: f64 = undefined;
+ if (self.surfaceAt(self.wlr_cursor.x, self.wlr_cursor.y, &sx, &sy)) |wlr_surface| {
+ // If input is allowed on the surface, send pointer enter and motion
+ // events. Note that wlroots won't actually send an enter event if
+ // the surface has already been entered.
+ if (self.seat.input_manager.inputAllowed(wlr_surface)) {
+ // The focus change must be checked before sending enter events
+ const focus_change = self.seat.wlr_seat.pointer_state.focused_surface != wlr_surface;
+
+ c.wlr_seat_pointer_notify_enter(self.seat.wlr_seat, wlr_surface, sx, sy);
+ c.wlr_seat_pointer_notify_motion(self.seat.wlr_seat, time, sx, sy);
+ if (View.fromWlrSurface(wlr_surface)) |view| {
+ // Change focus according to config
+ switch (config.focus_follows_cursor) {
+ .disabled => {},
+ .normal => {
+ // Only refocus when the cursor entered a new surface
+ if (focus_change) {
+ self.seat.focus(view);
+ root.startTransaction();
+ }
+ },
+ .strict => {
+ self.seat.focus(view);
+ root.startTransaction();
+ },
+ }
+ }
+
+ return;
+ }
+ } else {
+ // There is either no surface under the cursor or input is disallowed
+ // Reset the cursor image to the default and clear focus.
+ self.clearFocus();
+ }
+}
diff --git a/river/XdgToplevel.zig b/river/XdgToplevel.zig
index b448b53..ede27de 100644
--- a/river/XdgToplevel.zig
+++ b/river/XdgToplevel.zig
@@ -24,7 +24,6 @@ const log = @import("log.zig");
const util = @import("util.zig");
const Box = @import("Box.zig");
-const Mode = @import("Cursor.zig").Mode;
const Seat = @import("Seat.zig");
const View = @import("View.zig");
const ViewStack = @import("view_stack.zig").ViewStack;
@@ -312,7 +311,7 @@ fn handleRequestMove(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) voi
const self = @fieldParentPtr(Self, "listen_request_move", listener.?);
const event = util.voidCast(c.wlr_xdg_toplevel_move_event, data.?);
const seat = util.voidCast(Seat, event.seat.*.seat.*.data.?);
- Mode.enter(&seat.cursor, .move, self.view);
+ seat.cursor.enterMode(.move, self.view);
}
/// Called when the client asks to be resized via the cursor.
@@ -320,5 +319,5 @@ fn handleRequestResize(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) v
const self = @fieldParentPtr(Self, "listen_request_resize", listener.?);
const event = util.voidCast(c.wlr_xdg_toplevel_resize_event, data.?);
const seat = util.voidCast(Seat, event.seat.*.seat.*.data.?);
- Mode.enter(&seat.cursor, .resize, self.view);
+ seat.cursor.enterMode(.resize, self.view);
}