|
17 | 17 | // along with this program. If not, see <https://www.gnu.org/licenses/>. |
18 | 18 |
|
19 | 19 | const std = @import("std"); |
| 20 | +const Allocator = std.mem.Allocator; |
20 | 21 | const Node = @import("../Node.zig"); |
21 | 22 | const css = @import("../../browser/dom/css.zig"); |
22 | 23 | const parser = @import("../../browser/netsurf.zig"); |
23 | 24 | const dom_node = @import("../../browser/dom/node.zig"); |
| 25 | +const DOMRect = @import("../../browser/dom/element.zig").Element.DOMRect; |
24 | 26 |
|
25 | 27 | pub fn processMessage(cmd: anytype) !void { |
26 | 28 | const action = std.meta.stringToEnum(enum { |
@@ -237,102 +239,80 @@ fn describeNode(cmd: anytype) !void { |
237 | 239 | depth: u32 = 1, |
238 | 240 | pierce: bool = false, |
239 | 241 | })) orelse return error.InvalidParams; |
240 | | - if (params.backendNodeId != null or params.depth != 1 or params.pierce) { |
241 | | - return error.NotYetImplementedParams; |
242 | | - } |
243 | 242 |
|
| 243 | + if (params.depth != 1 or params.pierce) return error.NotYetImplementedParams; |
244 | 244 | const bc = cmd.browser_context orelse return error.BrowserContextNotLoaded; |
245 | 245 |
|
246 | | - const input_node_id = params.nodeId orelse params.backendNodeId; |
247 | | - if (input_node_id != null) { |
248 | | - const node = bc.node_registry.lookup_by_id.get(params.nodeId.?) orelse return error.NodeNotFound; |
249 | | - return cmd.sendResult(.{ .node = bc.nodeWriter(node, .{}) }, .{}); |
250 | | - } |
251 | | - if (params.objectId != null) { |
252 | | - // Retrieve the object from which ever context it is in. |
253 | | - const parser_node = try bc.inspector.getNodePtr(cmd.arena, params.objectId.?); |
254 | | - const node = try bc.node_registry.register(@ptrCast(parser_node)); |
255 | | - return cmd.sendResult(.{ .node = bc.nodeWriter(node, .{}) }, .{}); |
256 | | - } |
257 | | - return error.MissingParams; |
258 | | -} |
| 246 | + const node = try getNode(cmd.arena, bc, params.nodeId, params.backendNodeId, params.objectId); |
259 | 247 |
|
260 | | -// Note Element.DOMRect exists, but there is no need to couple them at this time. |
261 | | -const Rect = struct { |
262 | | - x: f64, |
263 | | - y: f64, |
264 | | - width: f64, |
265 | | - height: f64, |
266 | | -}; |
| 248 | + return cmd.sendResult(.{ .node = bc.nodeWriter(node, .{}) }, .{}); |
| 249 | +} |
267 | 250 |
|
268 | 251 | // An array of quad vertices, x immediately followed by y for each point, points clock-wise. |
269 | 252 | // Note Y points downward |
270 | 253 | // We are assuming the start/endpoint is not repeated. |
271 | 254 | const Quad = [8]f64; |
272 | 255 |
|
| 256 | +fn rectToQuad(rect: DOMRect) Quad { |
| 257 | + return Quad{ |
| 258 | + rect.x, |
| 259 | + rect.y, |
| 260 | + rect.x + rect.width, |
| 261 | + rect.y, |
| 262 | + rect.x + rect.width, |
| 263 | + rect.y + rect.height, |
| 264 | + rect.x, |
| 265 | + rect.y + rect.height, |
| 266 | + }; |
| 267 | +} |
| 268 | + |
273 | 269 | fn scrollIntoViewIfNeeded(cmd: anytype) !void { |
274 | | - const params = (try cmd.params(struct { |
| 270 | + _ = (try cmd.params(struct { |
275 | 271 | nodeId: ?Node.Id = null, |
276 | 272 | backendNodeId: ?u32 = null, |
277 | 273 | objectId: ?[]const u8 = null, |
278 | | - rect: ?Rect = null, |
| 274 | + rect: ?DOMRect = null, |
279 | 275 | })) orelse return error.InvalidParams; |
280 | 276 |
|
281 | | - var set_count: u2 = 0; // only 1 of nodeId backendNodeId objectId may be set |
282 | | - if (params.nodeId != null) set_count += 1; |
283 | | - if (params.backendNodeId != null) set_count += 1; |
284 | | - if (params.objectId != null) set_count += 1; |
285 | | - if (set_count != 1) return error.InvalidParams; |
| 277 | + // Only 1 of nodeId, backendNodeId, objectId may be set, but we don't want to error unnecessarily |
| 278 | + // TBD what do other browsers do in this user error sceneario? |
286 | 279 |
|
287 | 280 | // Since element.scrollIntoViewIfNeeded is a no-op we do not bother retrieving the node. |
288 | 281 | // This however also means we also do not error in case the node is not found. |
289 | 282 |
|
290 | 283 | return cmd.sendResult(null, .{}); |
291 | 284 | } |
292 | 285 |
|
| 286 | +fn getNode(arena: Allocator, browser_context: anytype, node_id: ?Node.Id, backend_node_id: ?Node.Id, object_id: ?[]const u8) !*Node { |
| 287 | + const input_node_id = node_id orelse backend_node_id; |
| 288 | + if (input_node_id) |input_node_id_| { |
| 289 | + return browser_context.node_registry.lookup_by_id.get(input_node_id_) orelse return error.NodeNotFound; |
| 290 | + } |
| 291 | + if (object_id) |object_id_| { |
| 292 | + // Retrieve the object from which ever context it is in. |
| 293 | + const parser_node = try browser_context.inspector.getNodePtr(arena, object_id_); |
| 294 | + return try browser_context.node_registry.register(@ptrCast(parser_node)); |
| 295 | + } |
| 296 | + return error.MissingParams; |
| 297 | +} |
| 298 | + |
293 | 299 | fn getContentQuads(cmd: anytype) !void { |
294 | 300 | const params = (try cmd.params(struct { |
295 | 301 | nodeId: ?Node.Id = null, |
296 | | - backendNodeId: ?u32 = null, |
| 302 | + backendNodeId: ?Node.Id = null, |
297 | 303 | objectId: ?[]const u8 = null, |
298 | 304 | })) orelse return error.InvalidParams; |
299 | 305 |
|
300 | | - var set_count: u2 = 0; // only 1 of nodeId backendNodeId objectId may be set |
301 | | - if (params.nodeId != null) set_count += 1; |
302 | | - if (params.backendNodeId != null) set_count += 1; |
303 | | - if (params.objectId != null) set_count += 1; |
304 | | - if (set_count != 1) return error.InvalidParams; |
305 | | - |
306 | 306 | const bc = cmd.browser_context orelse return error.BrowserContextNotLoaded; |
307 | 307 |
|
308 | | - const node = blk: { |
309 | | - const input_node_id = params.nodeId orelse params.backendNodeId; |
310 | | - if (input_node_id != null) { |
311 | | - const node = bc.node_registry.lookup_by_id.get(params.nodeId.?) orelse return error.NodeNotFound; |
312 | | - break :blk node; |
313 | | - } |
314 | | - if (params.objectId != null) { |
315 | | - const parser_node = try bc.inspector.getNodePtr(cmd.arena, params.objectId.?); |
316 | | - const node = try bc.node_registry.register(@ptrCast(parser_node)); |
317 | | - break :blk node; |
318 | | - } |
319 | | - unreachable; |
320 | | - }; |
| 308 | + const node = try getNode(cmd.arena, bc, params.nodeId, params.backendNodeId, params.objectId); |
321 | 309 |
|
322 | | - if (try parser.nodeType(node._node) != .element) return error.NodeISNotAnElement; |
| 310 | + if (try parser.nodeType(node._node) != .element) return error.NodeIsNotAnElement; |
| 311 | + // TBD should the funcion work on nodes that are not elements, but may have geometry like Window? |
323 | 312 |
|
324 | 313 | const element = parser.nodeToElement(node._node); |
325 | 314 | const rect = try bc.session.page.?.state.renderer.getRect(element); |
326 | | - const quad = Quad{ |
327 | | - rect.x, |
328 | | - rect.y, |
329 | | - rect.x + rect.width, |
330 | | - rect.y, |
331 | | - rect.x + rect.width, |
332 | | - rect.y + rect.height, |
333 | | - rect.x, |
334 | | - rect.y + rect.height, |
335 | | - }; |
| 315 | + const quad = rectToQuad(rect); |
336 | 316 |
|
337 | 317 | return cmd.sendResult(.{ .quads = &.{quad} }, .{}); |
338 | 318 | } |
|
0 commit comments