Skip to content

feat: MacOS scroll 支持#1224

Open
YJBeetle wants to merge 7 commits intoMaaXYZ:mainfrom
YJBeetle:MacOSScroll
Open

feat: MacOS scroll 支持#1224
YJBeetle wants to merge 7 commits intoMaaXYZ:mainfrom
YJBeetle:MacOSScroll

Conversation

@YJBeetle
Copy link
Contributor

@YJBeetle YJBeetle commented Mar 23, 2026

本PR增加了 MacOS scroll 支持

由 Sourcery 提供的摘要

在各控制单元中添加对 macOS 滚动的支持,并更新 macOS 测试 UI 以验证滚动行为。

新功能:

  • 通过 PostToPidInput 为以 PID 为目标的 macOS 控制器启用滚轮输入。
  • 基于当前光标位置,为 macOS 控制器启用全局滚轮输入。
  • ControllerAgent 中添加 macOS 控制器滚动处理路径,使 macOS 单元可以处理滚动操作。

增强内容:

  • 更新 macOS 测试 GUI,使其使用带有可见且需要滚动元素的可滚动画布,并调整窗口/布局大小。
  • 改进在 macOS 上创建鼠标和键盘 CGEvent 时的日志记录和错误处理。
  • 调整 macOS bee 模板的背景颜色,使其更好地匹配测试 UI。

文档:

  • 在英文和中文的一体化界面及管线协议文档中,记录 Win32、macOS 和自定义控制器支持滚动操作。

测试:

  • 扩展 macOS 测试应用,以记录滚轮事件,并通过可滚动画布对滚动效果进行可视化验证。
Original summary in English

Summary by Sourcery

Add macOS scroll support across the control units and update macOS test UI to exercise scroll behavior.

New Features:

  • Enable scroll wheel input for macOS PID-targeted controllers via PostToPidInput.
  • Enable global scroll wheel input for macOS controllers using the current cursor location.
  • Add macOS controller scroll handling path in ControllerAgent so macOS units can process scroll actions.

Enhancements:

  • Update the macOS test GUI to use a scrollable canvas with visible elements requiring scrolling and adjust window/layout sizing.
  • Improve logging and error handling when creating mouse and keyboard CGEvents on macOS.
  • Adjust the macOS bee template background color to better match the test UI.

Documentation:

  • Document that scroll operations are supported by Win32, macOS, and custom controllers in both English and Chinese integrated interface and pipeline protocol docs.

Tests:

  • Extend the macOS test application to log scroll wheel events and visually validate scrolling via a scrollable canvas.

Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - 我发现了 3 个问题,并给出了一些整体上的反馈:

  • PostToPidInput::scroll 中,[nsEvent0 CGEvent] 返回的是一个已保留 (retained) 的 CGEventRef,但从未被 CFRelease,这会导致内存泄漏;如果你继续使用 nsEvent0 这种做法,务必在 CGEventPostToPid 之后释放 event0
  • 使用 KVC 将 nsEvent0type 修改为 NSEventTypeScrollWheel[nsEvent0 setValue:@(NSEventTypeScrollWheel) forKey:@"type"])依赖于私有实现细节,在不同 macOS 版本之间可能不够稳定;建议考虑完全通过 CGEventCreateScrollWheelEvent 来构造所需的滚动事件。
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In `PostToPidInput::scroll`, `[nsEvent0 CGEvent]` returns a retained `CGEventRef` that is never `CFRelease`d, causing a leak; if you keep the `nsEvent0` approach, make sure to release `event0` after `CGEventPostToPid`.
- The use of KVC to mutate `nsEvent0`'s `type` to `NSEventTypeScrollWheel` (`[nsEvent0 setValue:@(NSEventTypeScrollWheel) forKey:@"type"]`) relies on private implementation details and may be fragile across macOS versions; consider constructing the needed scroll events purely via `CGEventCreateScrollWheelEvent` instead.

## Individual Comments

### Comment 1
<location path="source/MaaMacOSControlUnit/Input/PostToPidInput.mm" line_range="171-180" />
<code_context>
+        return false;
+    }
+    [nsEvent0 setValue:@(NSEventTypeScrollWheel) forKey:@"type"];
+    CGEventRef event0 = [nsEvent0 CGEvent];
+    if (!event0) {
+        LogError << "Failed to create scroll event0";
+        return false;
+    }
+
+    CGEventRef event1 = CGEventCreateScrollWheelEvent(nullptr, kCGScrollEventUnitPixel, 2, dy, dx);
+    if (!event1) {
+        LogError << "Failed to create scroll event1";
+        return false;
+    }
+
+    CGEventPostToPid(pid_, event0);
+    CGEventPostToPid(pid_, event1);
+
</code_context>
<issue_to_address>
**issue (bug_risk):** CGEventRef from NSEvent is never released, causing a leak (and on error path too).

Since `[nsEvent0 CGEvent]` returns a retained Core Foundation object, it must be `CFRelease`d on both success and failure paths. For example:

```objc
CGEventRef event0 = [nsEvent0 CGEvent];
if (!event0) {
    LogError << "Failed to create scroll event0";
    return false;
}

CGEventRef event1 = CGEventCreateScrollWheelEvent(nullptr, kCGScrollEventUnitPixel, 2, dy, dx);
if (!event1) {
    LogError << "Failed to create scroll event1";
    CFRelease(event0);
    return false;
}

CGEventPostToPid(pid_, event0);
CGEventPostToPid(pid_, event1);

CFRelease(event0);
CFRelease(event1);
```

This ensures proper ownership and no leaks on any path.
</issue_to_address>

### Comment 2
<location path="docs/en_us/2.2-IntegratedInterfaceOverview.md" line_range="474" />
<code_context>
 > [!NOTE]
 >
-> - Win32 controllers and custom controllers that implement `scroll` support scroll operations.
+> - Win32, MacOS, and custom controllers that implement `scroll` support scroll operations.
 > - Posting scroll to a controller that does not implement `scroll` will cause the action to fail.
 > - The `dx`/`dy` values are sent directly as scroll increments. The Windows standard wheel increment is 120 (WHEEL_DELTA) per notch. Using multiples of 120 is recommended for best compatibility.
</code_context>
<issue_to_address>
**suggestion (typo):** Consider using the standard platform spelling "macOS" instead of "MacOS".

Apple’s official platform name is "macOS"; please update this reference for accurate, consistent naming.

```suggestion
> - Win32, macOS, and custom controllers that implement `scroll` support scroll operations.
```
</issue_to_address>

### Comment 3
<location path="docs/en_us/3.1-PipelineProtocol.md" line_range="1103" />
<code_context>
 > [!NOTE]
 >
-> - Win32 controllers and custom controllers that implement `scroll` support scroll operations.
+> - Win32, MacOS, and custom controllers that implement `scroll` support scroll operations.
 > - Posting scroll to a controller that does not implement `scroll` will cause the action to fail.
 > - The `dx`/`dy` values are sent directly as scroll increments. The Windows standard wheel increment is 120 (WHEEL_DELTA) per notch. Using multiples of 120 is recommended for best compatibility.
</code_context>
<issue_to_address>
**suggestion (typo):** Consider changing "MacOS" to the standard "macOS".

Apple’s official branding uses the lowercase “macOS” form.

```suggestion
> - Win32, macOS, and custom controllers that implement `scroll` support scroll operations.
```
</issue_to_address>

Sourcery 对开源项目免费——如果你觉得我们的代码审查有帮助,欢迎帮忙转发分享 ✨
帮我变得更有用!请对每条评论点 👍 或 👎,我会根据你的反馈改进后续的代码审查。
Original comment in English

Hey - I've found 3 issues, and left some high level feedback:

  • In PostToPidInput::scroll, [nsEvent0 CGEvent] returns a retained CGEventRef that is never CFReleased, causing a leak; if you keep the nsEvent0 approach, make sure to release event0 after CGEventPostToPid.
  • The use of KVC to mutate nsEvent0's type to NSEventTypeScrollWheel ([nsEvent0 setValue:@(NSEventTypeScrollWheel) forKey:@"type"]) relies on private implementation details and may be fragile across macOS versions; consider constructing the needed scroll events purely via CGEventCreateScrollWheelEvent instead.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In `PostToPidInput::scroll`, `[nsEvent0 CGEvent]` returns a retained `CGEventRef` that is never `CFRelease`d, causing a leak; if you keep the `nsEvent0` approach, make sure to release `event0` after `CGEventPostToPid`.
- The use of KVC to mutate `nsEvent0`'s `type` to `NSEventTypeScrollWheel` (`[nsEvent0 setValue:@(NSEventTypeScrollWheel) forKey:@"type"]`) relies on private implementation details and may be fragile across macOS versions; consider constructing the needed scroll events purely via `CGEventCreateScrollWheelEvent` instead.

## Individual Comments

### Comment 1
<location path="source/MaaMacOSControlUnit/Input/PostToPidInput.mm" line_range="171-180" />
<code_context>
+        return false;
+    }
+    [nsEvent0 setValue:@(NSEventTypeScrollWheel) forKey:@"type"];
+    CGEventRef event0 = [nsEvent0 CGEvent];
+    if (!event0) {
+        LogError << "Failed to create scroll event0";
+        return false;
+    }
+
+    CGEventRef event1 = CGEventCreateScrollWheelEvent(nullptr, kCGScrollEventUnitPixel, 2, dy, dx);
+    if (!event1) {
+        LogError << "Failed to create scroll event1";
+        return false;
+    }
+
+    CGEventPostToPid(pid_, event0);
+    CGEventPostToPid(pid_, event1);
+
</code_context>
<issue_to_address>
**issue (bug_risk):** CGEventRef from NSEvent is never released, causing a leak (and on error path too).

Since `[nsEvent0 CGEvent]` returns a retained Core Foundation object, it must be `CFRelease`d on both success and failure paths. For example:

```objc
CGEventRef event0 = [nsEvent0 CGEvent];
if (!event0) {
    LogError << "Failed to create scroll event0";
    return false;
}

CGEventRef event1 = CGEventCreateScrollWheelEvent(nullptr, kCGScrollEventUnitPixel, 2, dy, dx);
if (!event1) {
    LogError << "Failed to create scroll event1";
    CFRelease(event0);
    return false;
}

CGEventPostToPid(pid_, event0);
CGEventPostToPid(pid_, event1);

CFRelease(event0);
CFRelease(event1);
```

This ensures proper ownership and no leaks on any path.
</issue_to_address>

### Comment 2
<location path="docs/en_us/2.2-IntegratedInterfaceOverview.md" line_range="474" />
<code_context>
 > [!NOTE]
 >
-> - Win32 controllers and custom controllers that implement `scroll` support scroll operations.
+> - Win32, MacOS, and custom controllers that implement `scroll` support scroll operations.
 > - Posting scroll to a controller that does not implement `scroll` will cause the action to fail.
 > - The `dx`/`dy` values are sent directly as scroll increments. The Windows standard wheel increment is 120 (WHEEL_DELTA) per notch. Using multiples of 120 is recommended for best compatibility.
</code_context>
<issue_to_address>
**suggestion (typo):** Consider using the standard platform spelling "macOS" instead of "MacOS".

Apple’s official platform name is "macOS"; please update this reference for accurate, consistent naming.

```suggestion
> - Win32, macOS, and custom controllers that implement `scroll` support scroll operations.
```
</issue_to_address>

### Comment 3
<location path="docs/en_us/3.1-PipelineProtocol.md" line_range="1103" />
<code_context>
 > [!NOTE]
 >
-> - Win32 controllers and custom controllers that implement `scroll` support scroll operations.
+> - Win32, MacOS, and custom controllers that implement `scroll` support scroll operations.
 > - Posting scroll to a controller that does not implement `scroll` will cause the action to fail.
 > - The `dx`/`dy` values are sent directly as scroll increments. The Windows standard wheel increment is 120 (WHEEL_DELTA) per notch. Using multiples of 120 is recommended for best compatibility.
</code_context>
<issue_to_address>
**suggestion (typo):** Consider changing "MacOS" to the standard "macOS".

Apple’s official branding uses the lowercase “macOS” form.

```suggestion
> - Win32, macOS, and custom controllers that implement `scroll` support scroll operations.
```
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@YJBeetle
Copy link
Contributor Author

  • 使用 KVC 将 nsEvent0type 修改为 NSEventTypeScrollWheel[nsEvent0 setValue:@(NSEventTypeScrollWheel) forKey:@"type"])依赖于私有实现细节,在不同 macOS 版本之间可能不够稳定;建议考虑完全通过 CGEventCreateScrollWheelEvent 来构造所需的滚动事件。

PostToPid 版的 scroll 比较魔幻 直接 CGEventCreateScrollWheelEvent 构造的event无法被目标接受(就像鼠标事件一样,可能是缺少目标的windowID) 但是在发送这个event之前发一个被魔改的 NSEvent 就可以实现滚动

@YJBeetle
Copy link
Contributor Author

YJBeetle commented Mar 23, 2026

  • PostToPidInput::scroll 中,[nsEvent0 CGEvent] 返回的是一个已保留 (retained) 的 CGEventRef,但从未被 CFRelease,这会导致内存泄漏;如果你继续使用 nsEvent0 这种做法,务必在 CGEventPostToPid 之后释放 event0

[nsEvent0 CGEvent] 是一个 getter,不是 Create 或者 Copy,返回的对象并不拥有,生命周期由nsEvent0负责,不能调 CFRelease。

@YJBeetle YJBeetle changed the title MacOS scroll 支持 feat: MacOS scroll 支持 Mar 23, 2026
@MistEO MistEO requested review from Copilot and neko-para March 23, 2026 17:13
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds macOS scroll support to the control units and wires the framework’s controller agent to route Scroll actions to macOS controllers, alongside updating the macOS test GUI/pipeline and documenting scroll support.

Changes:

  • Implement scroll event injection for macOS controllers (PID-targeted and global-event modes) and route Scroll in ControllerAgent to macOS control units.
  • Update macOS test GUI and pipeline to visually exercise scroll behavior (scrollable canvas + new scroll steps).
  • Update English docs to state macOS controllers support scroll operations.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
source/MaaMacOSControlUnit/Input/PostToPidInput.mm Adds PID-targeted scroll injection via Quartz/AppKit event creation.
source/MaaMacOSControlUnit/Input/GlobalEventInput.mm Adds global scroll injection using current cursor position and improves event creation error handling.
source/MaaFramework/Controller/ControllerAgent.cpp Routes Scroll actions to macOS control units (in addition to Win32/custom).
test/macos_test/MacOSTestGUI.mm Reworks the macOS test window to include a scrollable canvas and logs scroll events.
test/macos_test/MacOSTestGUI.h Declares the new scroll callback hook used by the test GUI.
test/macos_test/pipeline.json Adds scroll test nodes (down/up/right) to the macOS test pipeline.
test/macos_test/GenerateBee.py Adjusts the bee template background color to match the updated test UI.
docs/en_us/3.1-PipelineProtocol.md Updates scroll note to include macOS controllers.
docs/en_us/2.2-IntegratedInterfaceOverview.md Updates controller API scroll note to include macOS controllers.

Comment on lines +176 to +178
CGEventRef pos_event = CGEventCreate(nullptr);
CGPoint location = CGEventGetLocation(pos_event);
CFRelease(pos_event);
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

scroll() uses CGEventCreate(nullptr) without a null check, then immediately calls CGEventGetLocation(pos_event) and CFRelease(pos_event). If CGEventCreate returns null, this will crash. Add a null check (and only release when non-null), or use a safer way to query the current cursor location.

Suggested change
CGEventRef pos_event = CGEventCreate(nullptr);
CGPoint location = CGEventGetLocation(pos_event);
CFRelease(pos_event);
CGPoint location = CGPointZero;
CGEventRef pos_event = CGEventCreate(nullptr);
if (pos_event) {
location = CGEventGetLocation(pos_event);
CFRelease(pos_event);
} else {
LogWarn << "Warning: Failed to create position event, using default location (0, 0)";
}

Copilot uses AI. Check for mistakes.
Comment on lines +180 to +188
// wheel1: 垂直滚动(正值向上,负值向下),wheel2: 水平滚动(正值向左,负值向右)
CGEventRef event = CGEventCreateScrollWheelEvent(nullptr, kCGScrollEventUnitPixel, 2, dy, dx);
if (!event) {
LogError << "Failed to create scroll wheel event";
return false;
}

CGEventSetLocation(event, location);
CGEventPost(kCGHIDEventTap, event);
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The horizontal scroll direction comment/code path appears to conflict with the documented Scroll semantics (docs say dx > 0 scrolls right, dx < 0 scrolls left). Here wheel2 is described as dx > 0 scroll left, dx < 0 scroll right, and dx is passed through directly. Please align macOS behavior with the protocol (likely negate dx when constructing the CGEvent, and update the comment accordingly).

Copilot uses AI. Check for mistakes.
Comment on lines +156 to +187
NSPoint location = NSMakePoint(latest_touch_x_, window_h_ - latest_touch_y_);
NSEvent* nsEvent0 = [NSEvent mouseEventWithType:NSEventTypeMouseMoved
location:location
modifierFlags:0
timestamp:[NSDate timeIntervalSinceReferenceDate]
windowNumber:window_id_
context:nil
eventNumber:0
clickCount:1
pressure:0];
if (!nsEvent0) {
LogError << "Failed to create scroll nsEvent0";
return false;
}
[nsEvent0 setValue:@(NSEventTypeScrollWheel) forKey:@"type"];
CGEventRef event0 = [nsEvent0 CGEvent];
if (!event0) {
LogError << "Failed to create scroll event0";
return false;
}

CGEventRef event1 = CGEventCreateScrollWheelEvent(nullptr, kCGScrollEventUnitPixel, 2, dy, dx);
if (!event1) {
LogError << "Failed to create scroll event1";
return false;
}

CGEventPostToPid(pid_, event0);
CGEventPostToPid(pid_, event1);

CFRelease(event1);

Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nsEvent0 setValue:@(NSEventTypeScrollWheel) forKey:@"type"] relies on KVC to mutate an NSEvent's (read-only) type. This is not a public/safe API and can raise an exception at runtime on some macOS versions. Prefer constructing a proper scroll CGEvent (or NSEvent if supported) without KVC hacks.

Suggested change
NSPoint location = NSMakePoint(latest_touch_x_, window_h_ - latest_touch_y_);
NSEvent* nsEvent0 = [NSEvent mouseEventWithType:NSEventTypeMouseMoved
location:location
modifierFlags:0
timestamp:[NSDate timeIntervalSinceReferenceDate]
windowNumber:window_id_
context:nil
eventNumber:0
clickCount:1
pressure:0];
if (!nsEvent0) {
LogError << "Failed to create scroll nsEvent0";
return false;
}
[nsEvent0 setValue:@(NSEventTypeScrollWheel) forKey:@"type"];
CGEventRef event0 = [nsEvent0 CGEvent];
if (!event0) {
LogError << "Failed to create scroll event0";
return false;
}
CGEventRef event1 = CGEventCreateScrollWheelEvent(nullptr, kCGScrollEventUnitPixel, 2, dy, dx);
if (!event1) {
LogError << "Failed to create scroll event1";
return false;
}
CGEventPostToPid(pid_, event0);
CGEventPostToPid(pid_, event1);
CFRelease(event1);
// 使用 CGEvent 原生滚动事件,避免通过 KVC 修改 NSEvent 的只读 type。
CGPoint location = CGPointMake(latest_touch_x_, latest_touch_y_);
CGEventRef event = CGEventCreateScrollWheelEvent(nullptr, kCGScrollEventUnitPixel, 2, dy, dx);
if (!event) {
LogError << "Failed to create scroll event";
return false;
}
CGEventSetLocation(event, location);
CGEventPostToPid(pid_, event);
CFRelease(event);

Copilot uses AI. Check for mistakes.
LogError << "Failed to create scroll event1";
return false;
}

Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The scroll CGEventRef event1 = CGEventCreateScrollWheelEvent(...) is posted without setting its location. Posting a separate event0 (built from a mouse event) won’t reliably associate the scroll delta with the intended point, especially since event0’s type is being modified. Set the scroll event’s location explicitly (and consider posting a normal mouse-move event first if needed), or derive the correct screen location and apply it to event1 via CGEventSetLocation.

Suggested change
// Ensure the scroll event has the correct location, matching the mouse event.
CGEventSetLocation(event1, CGEventGetLocation(event0));

Copilot uses AI. Check for mistakes.
Comment on lines +48 to +49
// 将滚动事件传递给父视图(NSScrollView),实现实际滚动
[super scrollWheel:event];
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

EventHandlingView’s scrollWheel: override is unlikely to run when the cursor is over the scrollable area, because scroll events will be dispatched to the NSScrollView/document view (CanvasView) under the cursor. Also, calling [super scrollWheel:event] on NSView doesn’t forward the event to the parent NSScrollView. If you want both logging and actual scrolling, handle scrollWheel: in the document view (or install an event monitor) and forward via the responder chain (e.g., [[self nextResponder] scrollWheel:event]).

Suggested change
// 将滚动事件传递给父视图(NSScrollView),实现实际滚动
[super scrollWheel:event];
// 将滚动事件通过响应链传递给父视图(例如 NSScrollView),实现实际滚动
[[self nextResponder] scrollWheel:event];

Copilot uses AI. Check for mistakes.
Comment on lines 160 to +172
// 创建自定义容器视图(支持事件处理)
EventHandlingView* containerView = [[EventHandlingView alloc] initWithFrame:NSMakeRect(0, 0, 400, 400) gui:this];

// 创建文本标签(上面)
NSTextField* textField = [[NSTextField alloc] initWithFrame:NSMakeRect(0, 320, 400, 60)];
[textField setStringValue:@"这是一个测试窗口,用于 MaaFW 识别。"];
[textField setEditable:NO];
[textField setBordered:NO];
[textField setBackgroundColor:[NSColor clearColor]];
[textField setAlignment:NSTextAlignmentCenter];
[textField setFont:[NSFont systemFontOfSize:14]];
[containerView addSubview:textField];

// 创建 emoji 标签(下面居中)
NSTextField* emojiField = [[NSTextField alloc] initWithFrame:NSMakeRect(150, 150, 100, 100)];
[emojiField setStringValue:@"🐝"];
[emojiField setEditable:NO];
[emojiField setBordered:NO];
[emojiField setBackgroundColor:[NSColor clearColor]];
[emojiField setAlignment:NSTextAlignmentCenter];
[emojiField setFont:[NSFont systemFontOfSize:100]];
[containerView addSubview:emojiField];
EventHandlingView* containerView = [[EventHandlingView alloc] initWithFrame:NSMakeRect(0, 0, 720, 720) gui:this];

// 可滚动子画布
NSScrollView* scrollView = [[NSScrollView alloc] initWithFrame:NSMakeRect(0, 40, 720, 680)];
[scrollView setHasVerticalScroller:YES];
[scrollView setHasHorizontalScroller:NO];
[scrollView setBorderType:NSLineBorder];

// 子画布(翻转坐标,原点在左上角)
CanvasView* canvasView = [[CanvasView alloc] initWithFrame:NSMakeRect(0, 0, 1440, 1360)];
[canvasView setWantsLayer:YES];
[canvasView.layer setBackgroundColor:[[NSColor colorWithWhite:0.95 alpha:1.0] CGColor]];
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After introducing the NSScrollView + CanvasView, the existing mouse event handlers in EventHandlingView (mouseDown/Dragged/Up) will no longer be triggered for interactions inside the scrollable canvas, because those events will target the document view instead. If these callbacks are still needed for the test harness, move the mouse handlers to CanvasView (or make the document view an EventHandlingView) so clicks/drags inside the canvas are still reported.

Copilot uses AI. Check for mistakes.
"focus": "Scroll Right Test!",
"action": "Scroll",
"target": "bee_recognition",
"dx": -360,
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This node is labeled "Scroll Right Test!" but sets dx to a negative value. The pipeline protocol docs define dx > 0 as scroll right and dx < 0 as scroll left, so this test appears to exercise the opposite direction (or the implementation uses inverted sign). Please make the test direction/sign consistent with the documented semantics (and with the macOS implementation).

Suggested change
"dx": -360,
"dx": 360,

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants