DragIcon: render using the scene graph
This commit is contained in:
		| @ -31,6 +31,7 @@ const server = &@import("main.zig").server; | |||||||
| const util = @import("util.zig"); | const util = @import("util.zig"); | ||||||
|  |  | ||||||
| const Config = @import("Config.zig"); | const Config = @import("Config.zig"); | ||||||
|  | const DragIcon = @import("DragIcon.zig"); | ||||||
| const LayerSurface = @import("LayerSurface.zig"); | const LayerSurface = @import("LayerSurface.zig"); | ||||||
| const LockSurface = @import("LockSurface.zig"); | const LockSurface = @import("LockSurface.zig"); | ||||||
| const Output = @import("Output.zig"); | const Output = @import("Output.zig"); | ||||||
| @ -523,6 +524,8 @@ fn handleTouchMotion( | |||||||
|         log.err("out of memory", .{}); |         log.err("out of memory", .{}); | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|  |     self.updateDragIcons(); | ||||||
|  |  | ||||||
|     if (server.root.at(lx, ly)) |result| { |     if (server.root.at(lx, ly)) |result| { | ||||||
|         self.seat.wlr_seat.touchNotifyMotion(event.time_msec, event.touch_id, result.sx, result.sy); |         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_dx, | ||||||
|         unaccel_dy, |         unaccel_dy, | ||||||
|     ); |     ); | ||||||
|  |  | ||||||
|     var dx: f64 = delta_x; |     var dx: f64 = delta_x; | ||||||
|     var dy: f64 = delta_y; |     var dy: f64 = delta_y; | ||||||
|     switch (self.mode) { |     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.wlr_cursor.move(device, dx, dy); | ||||||
|             self.checkFocusFollowsCursor(); |             self.checkFocusFollowsCursor(); | ||||||
|             self.passthrough(time); |             self.passthrough(time); | ||||||
|  |             self.updateDragIcons(); | ||||||
|         }, |         }, | ||||||
|         .down => |down| { |         .down => |down| { | ||||||
|             self.wlr_cursor.move(device, dx, dy); |             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.sx + (self.wlr_cursor.x - down.lx), | ||||||
|                 down.sy + (self.wlr_cursor.y - down.ly), |                 down.sy + (self.wlr_cursor.y - down.ly), | ||||||
|             ); |             ); | ||||||
|  |             self.updateDragIcons(); | ||||||
|         }, |         }, | ||||||
|         .move => |*data| { |         .move => |*data| { | ||||||
|             dx += data.delta_x; |             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), | ||||||
|  |                 ); | ||||||
|  |             }, | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | |||||||
| @ -23,40 +23,70 @@ const wl = @import("wayland").server.wl; | |||||||
| const server = &@import("main.zig").server; | const server = &@import("main.zig").server; | ||||||
| const util = @import("util.zig"); | const util = @import("util.zig"); | ||||||
|  |  | ||||||
| const Seat = @import("Seat.zig"); | const SceneNodeData = @import("SceneNodeData.zig"); | ||||||
|  |  | ||||||
| seat: *Seat, |  | ||||||
| wlr_drag_icon: *wlr.Drag.Icon, | wlr_drag_icon: *wlr.Drag.Icon, | ||||||
|  |  | ||||||
| // Accumulated x/y surface offset from the cursor/touch point position. | tree: *wlr.SceneTree, | ||||||
| sx: i32 = 0, | surface: *wlr.SceneTree, | ||||||
| sy: i32 = 0, |  | ||||||
|  |  | ||||||
| // Always active |  | ||||||
| destroy: wl.Listener(*wlr.Drag.Icon) = wl.Listener(*wlr.Drag.Icon).init(handleDestroy), | 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), | 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 { | pub fn create(wlr_drag_icon: *wlr.Drag.Icon) error{OutOfMemory}!void { | ||||||
|     drag_icon.* = .{ .seat = seat, .wlr_drag_icon = wlr_drag_icon }; |     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.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); |     wlr_drag_icon.surface.events.commit.add(&drag_icon.commit); | ||||||
| } | } | ||||||
|  |  | ||||||
| fn handleDestroy(listener: *wl.Listener(*wlr.Drag.Icon), _: *wlr.Drag.Icon) void { | fn handleDestroy(listener: *wl.Listener(*wlr.Drag.Icon), _: *wlr.Drag.Icon) void { | ||||||
|     const drag_icon = @fieldParentPtr(DragIcon, "destroy", listener); |     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.destroy.link.remove(); | ||||||
|  |     drag_icon.map.link.remove(); | ||||||
|  |     drag_icon.unmap.link.remove(); | ||||||
|     drag_icon.commit.link.remove(); |     drag_icon.commit.link.remove(); | ||||||
|  |  | ||||||
|     util.gpa.destroy(drag_icon); |     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 { | fn handleCommit(listener: *wl.Listener(*wlr.Surface), surface: *wlr.Surface) void { | ||||||
|     const drag_icon = @fieldParentPtr(DragIcon, "commit", listener); |     const drag_icon = @fieldParentPtr(DragIcon, "commit", listener); | ||||||
|  |  | ||||||
|     drag_icon.sx += surface.current.dx; |     drag_icon.surface.node.setPosition( | ||||||
|     drag_icon.sy += surface.current.dy; |         drag_icon.surface.node.x + surface.current.dx, | ||||||
|  |         drag_icon.surface.node.y + surface.current.dy, | ||||||
|  |     ); | ||||||
| } | } | ||||||
|  | |||||||
| @ -68,6 +68,7 @@ tree: *wlr.SceneTree, | |||||||
| normal_content: *wlr.SceneTree, | normal_content: *wlr.SceneTree, | ||||||
| locked_content: *wlr.SceneTree, | locked_content: *wlr.SceneTree, | ||||||
|  |  | ||||||
|  | /// Child nodes of normal_content | ||||||
| layers: struct { | layers: struct { | ||||||
|     background_color_rect: *wlr.SceneRect, |     background_color_rect: *wlr.SceneRect, | ||||||
|     /// Background layer shell layer |     /// Background layer shell layer | ||||||
| @ -82,7 +83,7 @@ layers: struct { | |||||||
|     fullscreen: *wlr.SceneTree, |     fullscreen: *wlr.SceneTree, | ||||||
|     /// Overlay layer shell layer |     /// Overlay layer shell layer | ||||||
|     overlay: *wlr.SceneTree, |     overlay: *wlr.SceneTree, | ||||||
|     /// Xdg popups, Xwayland override redirect windows |     /// xdg-popups of views and layer-shell surfaces | ||||||
|     popups: *wlr.SceneTree, |     popups: *wlr.SceneTree, | ||||||
| }, | }, | ||||||
|  |  | ||||||
| @ -166,7 +167,7 @@ pub fn create(wlr_output: *wlr.Output) !void { | |||||||
|     var height: c_int = undefined; |     var height: c_int = undefined; | ||||||
|     wlr_output.effectiveResolution(&width, &height); |     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(); |     const normal_content = try tree.createSceneTree(); | ||||||
|  |  | ||||||
|     self.* = .{ |     self.* = .{ | ||||||
|  | |||||||
| @ -37,6 +37,16 @@ const ViewStack = @import("view_stack.zig").ViewStack; | |||||||
| const XwaylandOverrideRedirect = @import("XwaylandOverrideRedirect.zig"); | const XwaylandOverrideRedirect = @import("XwaylandOverrideRedirect.zig"); | ||||||
|  |  | ||||||
| scene: *wlr.Scene, | 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), | 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); |     const transaction_timer = try event_loop.addTimer(*Self, handleTransactionTimeout, self); | ||||||
|     errdefer transaction_timer.remove(); |     errdefer transaction_timer.remove(); | ||||||
|  |  | ||||||
|  |     const outputs = try scene.tree.createSceneTree(); | ||||||
|  |  | ||||||
|     // TODO get rid of this hack somehow |     // TODO get rid of this hack somehow | ||||||
|     const noop_wlr_output = try server.headless_backend.headlessAddOutput(1920, 1080); |     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); |     noop_tree.node.setEnabled(false); | ||||||
|  |  | ||||||
|     self.* = .{ |     self.* = .{ | ||||||
|         .scene = scene, |         .scene = scene, | ||||||
|  |         .layers = .{ | ||||||
|  |             .outputs = outputs, | ||||||
|  |             .drag_icons = try scene.tree.createSceneTree(), | ||||||
|  |         }, | ||||||
|         .output_layout = output_layout, |         .output_layout = output_layout, | ||||||
|         .output_manager = try wlr.OutputManagerV1.create(server.wl_server), |         .output_manager = try wlr.OutputManagerV1.create(server.wl_server), | ||||||
|         .power_manager = try wlr.OutputPowerManagerV1.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 { | pub fn at(self: Self, lx: f64, ly: f64) ?AtResult { | ||||||
|     var sx: f64 = undefined; |     var sx: f64 = undefined; | ||||||
|     var sy: 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: { |     const surface: ?*wlr.Surface = blk: { | ||||||
|         if (node_at.type == .buffer) { |         if (node_at.type == .buffer) { | ||||||
|  | |||||||
| @ -92,7 +92,6 @@ drag: enum { | |||||||
|     pointer, |     pointer, | ||||||
|     touch, |     touch, | ||||||
| } = .none, | } = .none, | ||||||
| drag_icon: ?*DragIcon = null, |  | ||||||
|  |  | ||||||
| request_set_selection: wl.Listener(*wlr.Seat.event.RequestSetSelection) = | request_set_selection: wl.Listener(*wlr.Seat.event.RequestSetSelection) = | ||||||
|     wl.Listener(*wlr.Seat.event.RequestSetSelection).init(handleRequestSetSelection), |     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); |     wlr_drag.events.destroy.add(&self.drag_destroy); | ||||||
|  |  | ||||||
|     if (wlr_drag.icon) |wlr_drag_icon| { |     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", .{}); |             log.err("out of memory", .{}); | ||||||
|             wlr_drag.seat_client.client.postNoMemory(); |             wlr_drag.seat_client.client.postNoMemory(); | ||||||
|             return; |             return; | ||||||
|         }; |         }; | ||||||
|         drag_icon.init(self, wlr_drag_icon); |  | ||||||
|         self.drag_icon = drag_icon; |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user