aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIsaac Freund <mail@isaacfreund.com>2023-02-16 16:54:53 +0100
committerIsaac Freund <mail@isaacfreund.com>2023-02-28 14:55:58 +0100
commit0b2272ec574052c8b196d959b3d0eee8e8a43f7b (patch)
tree298947ff0279d9a165a0efa5db52b69aefd152a5
parent0e0b585c44a2a29a3ce4b4618851cd332a741424 (diff)
downloadriver-0b2272ec574052c8b196d959b3d0eee8e8a43f7b.tar.gz
river-0b2272ec574052c8b196d959b3d0eee8e8a43f7b.tar.xz
DragIcon: render using the scene graph
-rw-r--r--river/Cursor.zig33
-rw-r--r--river/DragIcon.zig52
-rw-r--r--river/Output.zig5
-rw-r--r--river/Root.zig24
-rw-r--r--river/Seat.zig5
5 files changed, 99 insertions, 20 deletions
diff --git a/river/Cursor.zig b/river/Cursor.zig
index 810d360..ca8745e 100644
--- a/river/Cursor.zig
+++ b/river/Cursor.zig
@@ -31,6 +31,7 @@ const server = &@import("main.zig").server;
const util = @import("util.zig");
const Config = @import("Config.zig");
+const DragIcon = @import("DragIcon.zig");
const LayerSurface = @import("LayerSurface.zig");
const LockSurface = @import("LockSurface.zig");
const Output = @import("Output.zig");
@@ -523,6 +524,8 @@ fn handleTouchMotion(
log.err("out of memory", .{});
};
+ self.updateDragIcons();
+
if (server.root.at(lx, ly)) |result| {
self.seat.wlr_seat.touchNotifyMotion(event.time_msec, event.touch_id, result.sx, result.sy);
}
@@ -721,6 +724,7 @@ fn processMotion(self: *Self, device: *wlr.InputDevice, time: u32, delta_x: f64,
unaccel_dx,
unaccel_dy,
);
+
var dx: f64 = delta_x;
var dy: f64 = delta_y;
switch (self.mode) {
@@ -728,6 +732,7 @@ fn processMotion(self: *Self, device: *wlr.InputDevice, time: u32, delta_x: f64,
self.wlr_cursor.move(device, dx, dy);
self.checkFocusFollowsCursor();
self.passthrough(time);
+ self.updateDragIcons();
},
.down => |down| {
self.wlr_cursor.move(device, dx, dy);
@@ -736,6 +741,7 @@ fn processMotion(self: *Self, device: *wlr.InputDevice, time: u32, delta_x: f64,
down.sx + (self.wlr_cursor.x - down.lx),
down.sy + (self.wlr_cursor.y - down.ly),
);
+ self.updateDragIcons();
},
.move => |*data| {
dx += data.delta_x;
@@ -933,3 +939,30 @@ fn warp(self: *Self) void {
}
}
}
+
+fn updateDragIcons(self: *Self) void {
+ var it = server.root.layers.drag_icons.children.iterator(.forward);
+ while (it.next()) |node| {
+ const icon = @intToPtr(*DragIcon, node.data);
+
+ if (icon.wlr_drag_icon.drag.seat != self.seat.wlr_seat) continue;
+
+ switch (icon.wlr_drag_icon.drag.grab_type) {
+ .keyboard => unreachable,
+ .keyboard_pointer => {
+ icon.tree.node.setPosition(
+ @floatToInt(c_int, self.wlr_cursor.x),
+ @floatToInt(c_int, self.wlr_cursor.y),
+ );
+ },
+ .keyboard_touch => {
+ const touch_id = icon.wlr_drag_icon.drag.touch_id;
+ const point = self.touch_points.get(touch_id) orelse continue;
+ icon.tree.node.setPosition(
+ @floatToInt(c_int, point.lx),
+ @floatToInt(c_int, point.ly),
+ );
+ },
+ }
+ }
+}
diff --git a/river/DragIcon.zig b/river/DragIcon.zig
index 11683ea..bba55f2 100644
--- a/river/DragIcon.zig
+++ b/river/DragIcon.zig
@@ -23,40 +23,70 @@ const wl = @import("wayland").server.wl;
const server = &@import("main.zig").server;
const util = @import("util.zig");
-const Seat = @import("Seat.zig");
+const SceneNodeData = @import("SceneNodeData.zig");
-seat: *Seat,
wlr_drag_icon: *wlr.Drag.Icon,
-// Accumulated x/y surface offset from the cursor/touch point position.
-sx: i32 = 0,
-sy: i32 = 0,
+tree: *wlr.SceneTree,
+surface: *wlr.SceneTree,
-// Always active
destroy: wl.Listener(*wlr.Drag.Icon) = wl.Listener(*wlr.Drag.Icon).init(handleDestroy),
+map: wl.Listener(*wlr.Drag.Icon) = wl.Listener(*wlr.Drag.Icon).init(handleMap),
+unmap: wl.Listener(*wlr.Drag.Icon) = wl.Listener(*wlr.Drag.Icon).init(handleUnmap),
commit: wl.Listener(*wlr.Surface) = wl.Listener(*wlr.Surface).init(handleCommit),
-pub fn init(drag_icon: *DragIcon, seat: *Seat, wlr_drag_icon: *wlr.Drag.Icon) void {
- drag_icon.* = .{ .seat = seat, .wlr_drag_icon = wlr_drag_icon };
+pub fn create(wlr_drag_icon: *wlr.Drag.Icon) error{OutOfMemory}!void {
+ const tree = try server.root.layers.drag_icons.createSceneTree();
+ errdefer tree.node.destroy();
+
+ const drag_icon = try util.gpa.create(DragIcon);
+ errdefer util.gpa.destroy(drag_icon);
+
+ drag_icon.* = .{
+ .wlr_drag_icon = wlr_drag_icon,
+ .tree = tree,
+ .surface = try tree.createSceneSubsurfaceTree(wlr_drag_icon.surface),
+ };
+ tree.node.data = @ptrToInt(drag_icon);
+
+ tree.node.setEnabled(wlr_drag_icon.mapped);
wlr_drag_icon.events.destroy.add(&drag_icon.destroy);
+ wlr_drag_icon.events.map.add(&drag_icon.map);
+ wlr_drag_icon.events.unmap.add(&drag_icon.unmap);
wlr_drag_icon.surface.events.commit.add(&drag_icon.commit);
}
fn handleDestroy(listener: *wl.Listener(*wlr.Drag.Icon), _: *wlr.Drag.Icon) void {
const drag_icon = @fieldParentPtr(DragIcon, "destroy", listener);
- drag_icon.seat.drag_icon = null;
+ drag_icon.tree.node.destroy();
drag_icon.destroy.link.remove();
+ drag_icon.map.link.remove();
+ drag_icon.unmap.link.remove();
drag_icon.commit.link.remove();
util.gpa.destroy(drag_icon);
}
+fn handleMap(listener: *wl.Listener(*wlr.Drag.Icon), _: *wlr.Drag.Icon) void {
+ const drag_icon = @fieldParentPtr(DragIcon, "map", listener);
+
+ drag_icon.tree.node.setEnabled(true);
+}
+
+fn handleUnmap(listener: *wl.Listener(*wlr.Drag.Icon), _: *wlr.Drag.Icon) void {
+ const drag_icon = @fieldParentPtr(DragIcon, "unmap", listener);
+
+ drag_icon.tree.node.setEnabled(false);
+}
+
fn handleCommit(listener: *wl.Listener(*wlr.Surface), surface: *wlr.Surface) void {
const drag_icon = @fieldParentPtr(DragIcon, "commit", listener);
- drag_icon.sx += surface.current.dx;
- drag_icon.sy += surface.current.dy;
+ drag_icon.surface.node.setPosition(
+ drag_icon.surface.node.x + surface.current.dx,
+ drag_icon.surface.node.y + surface.current.dy,
+ );
}
diff --git a/river/Output.zig b/river/Output.zig
index 036495c..2917bad 100644
--- a/river/Output.zig
+++ b/river/Output.zig
@@ -68,6 +68,7 @@ tree: *wlr.SceneTree,
normal_content: *wlr.SceneTree,
locked_content: *wlr.SceneTree,
+/// Child nodes of normal_content
layers: struct {
background_color_rect: *wlr.SceneRect,
/// Background layer shell layer
@@ -82,7 +83,7 @@ layers: struct {
fullscreen: *wlr.SceneTree,
/// Overlay layer shell layer
overlay: *wlr.SceneTree,
- /// Xdg popups, Xwayland override redirect windows
+ /// xdg-popups of views and layer-shell surfaces
popups: *wlr.SceneTree,
},
@@ -166,7 +167,7 @@ pub fn create(wlr_output: *wlr.Output) !void {
var height: c_int = undefined;
wlr_output.effectiveResolution(&width, &height);
- const tree = try server.root.scene.tree.createSceneTree();
+ const tree = try server.root.layers.outputs.createSceneTree();
const normal_content = try tree.createSceneTree();
self.* = .{
diff --git a/river/Root.zig b/river/Root.zig
index 4e1e5b9..01a2b10 100644
--- a/river/Root.zig
+++ b/river/Root.zig
@@ -37,6 +37,16 @@ const ViewStack = @import("view_stack.zig").ViewStack;
const XwaylandOverrideRedirect = @import("XwaylandOverrideRedirect.zig");
scene: *wlr.Scene,
+/// All direct children of the root scene node
+layers: struct {
+ /// Parent tree for output trees which have their position updated when
+ /// outputs are moved in the layout.
+ outputs: *wlr.SceneTree,
+ /// Drag icons which have a position in layout coordinates that is updated
+ /// on cursor/touch point movement.
+ /// This tree is ignored by Root.at()
+ drag_icons: *wlr.SceneTree,
+},
new_output: wl.Listener(*wlr.Output) = wl.Listener(*wlr.Output).init(handleNewOutput),
@@ -94,12 +104,19 @@ pub fn init(self: *Self) !void {
const transaction_timer = try event_loop.addTimer(*Self, handleTransactionTimeout, self);
errdefer transaction_timer.remove();
+ const outputs = try scene.tree.createSceneTree();
+
// TODO get rid of this hack somehow
const noop_wlr_output = try server.headless_backend.headlessAddOutput(1920, 1080);
- const noop_tree = try scene.tree.createSceneTree();
+ const noop_tree = try outputs.createSceneTree();
noop_tree.node.setEnabled(false);
+
self.* = .{
.scene = scene,
+ .layers = .{
+ .outputs = outputs,
+ .drag_icons = try scene.tree.createSceneTree(),
+ },
.output_layout = output_layout,
.output_manager = try wlr.OutputManagerV1.create(server.wl_server),
.power_manager = try wlr.OutputPowerManagerV1.create(server.wl_server),
@@ -153,11 +170,12 @@ pub const AtResult = struct {
},
};
-/// Return information about what is currently rendered at the given layout coordinates.
+/// Return information about what is currently rendered in the Root.layers.outputs
+/// tree at the given layout coordinates.
pub fn at(self: Self, lx: f64, ly: f64) ?AtResult {
var sx: f64 = undefined;
var sy: f64 = undefined;
- const node_at = self.scene.tree.node.at(lx, ly, &sx, &sy) orelse return null;
+ const node_at = self.layers.outputs.node.at(lx, ly, &sx, &sy) orelse return null;
const surface: ?*wlr.Surface = blk: {
if (node_at.type == .buffer) {
diff --git a/river/Seat.zig b/river/Seat.zig
index d53532c..3dd6883 100644
--- a/river/Seat.zig
+++ b/river/Seat.zig
@@ -92,7 +92,6 @@ drag: enum {
pointer,
touch,
} = .none,
-drag_icon: ?*DragIcon = null,
request_set_selection: wl.Listener(*wlr.Seat.event.RequestSetSelection) =
wl.Listener(*wlr.Seat.event.RequestSetSelection).init(handleRequestSetSelection),
@@ -573,13 +572,11 @@ fn handleStartDrag(listener: *wl.Listener(*wlr.Drag), wlr_drag: *wlr.Drag) void
wlr_drag.events.destroy.add(&self.drag_destroy);
if (wlr_drag.icon) |wlr_drag_icon| {
- const drag_icon = util.gpa.create(DragIcon) catch {
+ DragIcon.create(wlr_drag_icon) catch {
log.err("out of memory", .{});
wlr_drag.seat_client.client.postNoMemory();
return;
};
- drag_icon.init(self, wlr_drag_icon);
- self.drag_icon = drag_icon;
}
}